Compare commits

...

6 Commits

Author SHA1 Message Date
theo@manjaro 706b7e0d92 Updated game over screen 2021-09-19 16:58:39 +02:00
theo@manjaro aa631c188e Added reset button 2021-09-19 15:58:01 +02:00
theo@manjaro f968827b7b Reduce camera shaking on spawn 2021-09-19 15:50:36 +02:00
theo@manjaro 74e05b11d2 Added monster behavior 2021-09-19 15:49:34 +02:00
theo@manjaro 693e4a49e8 Monsters kill other pinmiks 2021-09-19 15:07:59 +02:00
theo@manjaro eca2323d1a Added pause menu 2021-09-19 12:20:43 +02:00
45 changed files with 122 additions and 17 deletions

View File

@ -1,12 +1,12 @@
# Textures
All the textures are edited by myself to fit the [Famicube palette](https://lospec.com/palette-list/famicube)
I edited some textures to fit the [Famicube palette](https://lospec.com/palette-list/famicube)
## Tileset
[Buch - OpenGameArt](https://opengameart.org/content/the-field-of-the-floating-islands)
## Little characters
## "Pinmik" sprite ( I made the recolors )
[GraphxKid - OpenGameArt](https://opengameart.org/content/arcade-platformer-assets)
@ -21,3 +21,7 @@ All the textures are edited by myself to fit the [Famicube palette](https://losp
## Font
[Front End Dev - Grape Soda](https://fontenddev.com/fonts/grape-soda/)
## Dust particles
[GraphxKid - OpenGameArt](https://opengameart.org/content/items-and-elements)

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

View File

@ -136,6 +136,10 @@ def getunlocks(highscore):
unlocks["normal"].append("green")
if highscore>=250:
unlocks["normal"].append("blue")
if highscore>=500:
if highscore>=400:
unlocks["specials"].append("gold")
if highscore>=500:
unlocks["specials"].append("monster")
if highscore>=750:
unlocks["specials"].append("platinum")
return unlocks

View File

@ -58,6 +58,7 @@ class Game():
self.globals["scameray"] = 0
self.globals["debug"] = False
self.globals["highscore"] = highscore
self.globals["pause"] = False
self.scaleCamera()
self.globals["bgmvolume"] = bgm

View File

@ -7,6 +7,7 @@ class BaseObject():
self.game = game
self.sprite = game.sprite_lib["icon.png"]
self.spriteoffset = 0,0
self.handlepause = False
self.depth = 1 # Sa "profondeur", déterminera l'odre d'affichage des objets
def step(self):

View File

@ -40,7 +40,8 @@ class GameLoop():
objs = list(self.objects.values())
for i in objs:
i.step()
if i.handlepause and not game.globals["pause"] or not i.handlepause:
i.step()
def draw(self,game):
#Je secoue ma caméra

View File

@ -1,6 +1,8 @@
from gamedata.objects.base import BaseObject
from gamedata.objects.button import Button
import random
class GameOver(BaseObject):
def __init__(self,game):
super().__init__(0,0,game)
@ -14,6 +16,8 @@ class GameOver(BaseObject):
btn.click = fnBack
game.gameloop.summon(btn)
self.depth = -1
# Updating highscore
self.highscore = False
self.newunlocks = []
@ -70,6 +74,28 @@ class GameOver(BaseObject):
# Launch particles
self.launched = True
if self.highscore: # Balloons
offy = self.game.DISPLAY_HEIGHT+40
for i in range(2):
for direction in [-1,1]:
for color in ["yellow","red","blue"]:
sprite = [self.game.sprite_lib["particles/balloons/"+color+".png"]]
offx = self.game.DISPLAY_WIDTH/2-direction*self.game.DISPLAY_WIDTH/2*1.2
velx = (random.random()*3+1+2*i)*direction/2
vely = (random.random()+2)*-1
self.game.addParticle(sprite,offx,offy,velx=velx,vely=vely,flipx=direction==-1,fps=0.3)
# Confettis
for j in range(30):
for i in range(8):
color = random.choice(["red","blue","yellow"])
sprites = self.game.getSpriteDir("particles/confetti/"+color+"/")
offx = random.randint(0,self.game.DISPLAY_WIDTH)
offy = -40*i
velx = random.random()*2-1
vely = random.random()*5+2
self.game.addParticle(sprites,offx,offy,velx=velx,vely=vely,flipx=random.randint(0,1),fps=2)
if self.launched:
self.flashtimer.tick(self.game.dt)
@ -78,6 +104,9 @@ class GameOver(BaseObject):
self.displayscore = int(self.game.globals["score"])
def draw(self):
# Display night sky
self.game.window.blit(self.game.pygame.transform.scale(self.game.sprite_lib["skies/night.png"],[self.game.DISPLAY_WIDTH,self.game.DISPLAY_HEIGHT]),[0,0])
self.game.window.blit(self.game.sprite_lib["vignette.png"],[0,0])
# Display score
txt = self.game.fontfilebig.render("Score : "+str(int(self.displayscore)),False,self.color)
txt = self.game.pygame.transform.scale(txt,(round(txt.get_width()*self.scale),round(txt.get_height()*self.scale)))

View File

@ -11,6 +11,8 @@ class Clouds(BaseObject):
self.depth = -2
self.horoffset = 0
self.handlepause = True
def step(self):
self.horoffset+=self.game.dt*self.speed

View File

@ -13,13 +13,24 @@ class Lemming(BaseObject):
self.normalspeed = self.basespeed # Speed "objective"
self.speed = 0 # Current speed, leaning towards objective speed
self.scoreratio = 0.2
self.handlepause = True
self.scoreratio = 0.3
if skin=="gold":
self.basespeed*=1.2
self.scoreratio*=3
if skin=="platinum":
self.basespeed*=1.4
self.scoreratio*=5
if skin=="monster":
self.scoreratio*=6
self.skin = skin
self.maxhealth = 2 # Pinmiks can be attacked by the monsters
self.health = self.maxhealth
self.regen = 1
self.selected = False # If beeing redirected
self.anglemargin = 25
@ -59,6 +70,22 @@ class Lemming(BaseObject):
self.move(diffx*self.game.dt,diffy*self.game.dt)
self.health = min(self.maxhealth,self.health+self.regen*self.game.dt) # Regen live
# Attacking other pinmiks
if self.skin=="monster":
for pinmik in self.game.gameloop.findname("Lemming"):
if pinmik.skin!="monster":
if self.rect.collidepoint(pinmik.rect.center):
pinmik.health-=self.game.dt*3.5
if self.holdrect.collidepoint(pinmik.rect.center):
pinmik.health-=self.game.dt*2
# Lean towards middle
angle_to_mid = math.degrees(math.atan2(self.game.DISPLAY_HEIGHT/2-self.rect.center[1],self.game.DISPLAY_WIDTH/2-self.rect.center[0]))
if abs(angle_to_mid-self.direction-360)<abs(angle_to_mid-self.direction):
angle_to_mid-=360
self.direction += (angle_to_mid-self.direction)*self.game.dt*0.5
# Spawning dust particles if being launched
if self.speed > self.basespeed*1.5:
if self.dusttimer.tick(self.game.dt*(self.speed/self.basespeed)**2):
@ -92,8 +119,9 @@ class Lemming(BaseObject):
if 0<=gridx<len(self.tiles.grid[gridy]):
if self.tiles.grid[gridy][gridx]==1:
dead = False
if dead:
self.manager.death()
if dead or self.health<0:
if self.skin!="monster": # Monsters die without removing lives
self.manager.death()
if self.game.globals["scamerax"]*self.game.globals["scameray"]>5: # Avoiding shaking to much
self.game.globals["scamerax"]+=1
self.game.globals["scamerax"]+=1
@ -135,12 +163,21 @@ class Lemming(BaseObject):
self.holdrect[1]+=int(vely)
def draw(self):
if self.skin=="monster":
# Red aura
self.game.lib.drawcenter(self.game,self.game.sprite_lib["lemmings/monster/aura.png"],self.rect.center[0],self.rect.center[1])
# Shaking based on life
offx,offy = 0,0
if self.health<self.maxhealth:
shake = (1-(self.health/self.maxhealth))*4
offx = random.random()*shake*2-shake
offy = random.random()*shake*2-shake
orientation = self.orientations[int(self.direction%360/361*4)]
sprites = self.sprites[orientation]
self.game.lib.drawcenter(self.game,self.game.sprite_lib["lemmings/shadow.png"],self.rect.center[0]-self.game.globals["camerax"],self.rect.center[1]-self.game.globals["cameray"])
self.game.lib.drawcenter(self.game,sprites[int(self.spriteindex)%len(sprites)],self.rect.center[0]-self.game.globals["camerax"],self.rect.center[1]-self.game.globals["cameray"])
self.game.lib.drawcenter(self.game,self.game.sprite_lib["lemmings/shadow.png"],self.rect.center[0]-self.game.globals["camerax"]+offx,self.rect.center[1]-self.game.globals["cameray"]+offy)
self.game.lib.drawcenter(self.game,sprites[int(self.spriteindex)%len(sprites)],self.rect.center[0]-self.game.globals["camerax"]+offx,self.rect.center[1]-self.game.globals["cameray"]+offy)
if self.selected:
self.game.lib.drawcenter(self.game,self.game.sprite_lib["lemmings/selected.png"],self.rect.center[0]-self.game.globals["camerax"],self.rect.center[1]-self.game.globals["cameray"])
self.game.lib.drawcenter(self.game,self.game.sprite_lib["lemmings/selected.png"],self.rect.center[0]-self.game.globals["camerax"]+offx,self.rect.center[1]-self.game.globals["cameray"]+offy)
if self.game.globals["debug"]:
s = self.game.pygame.Surface(self.rect.size)
s.fill([255,0,0])

View File

@ -52,8 +52,12 @@ class Manager(BaseObject):
lemmings = self.game.gameloop.findname("Lemming")
nblemmings = len(lemmings) + len(self.game.gameloop.findname("Spawner"))
# Updating score
for lemming in lemmings:
self.score+=lemming.scoreratio*self.game.dt
if not self.game.globals["pause"]:
for lemming in lemmings:
self.score+=lemming.scoreratio*self.game.dt
# Pausing the game
if self.game.inputs["keys"]["escape"]["timer"]==1:
self.game.globals["pause"] = not self.game.globals["pause"]
# Spawning more lemmings
if (self.lives>0 and nblemmings>0):
if self.spawntimer.tick(self.game.dt):
@ -65,6 +69,7 @@ class Manager(BaseObject):
if self.endtimer.tick(self.game.dt):
self.game.globals["score"] = int(self.score)
self.game.scene = self.game.scenes.gameover
self.game.globals["pause"] = False
if self.invincible:
if self.deathtimer.tick(self.game.dt):
@ -105,9 +110,8 @@ class Manager(BaseObject):
self.game.realwindow.blit(txtsurfacelives,[20,20*2+txtsurfacescore.get_height()])
self.endrect.set_alpha((1-self.endtimer.getratio())*255)
if self.game.globals["pause"]:
self.endrect.set_alpha(100)
if self.endtimer.getloops()>=1:
self.endrect.set_alpha(255)
self.game.realwindow.blit(self.endrect,[0,0])

View File

@ -21,6 +21,8 @@ class Skies(BaseObject):
self.blackrectalpha = 0.5
self.handlepause = True
def step(self):
self.timeelapsed+=self.game.dt

View File

@ -12,6 +12,8 @@ class Spawner(BaseObject):
self.distance = game.DISPLAY_HEIGHT
self.timer = game.lib.Timer(2.5+random.random()) # Seconds of telegraph before spawning the lemming
self.handlepause = True
# Skin choosing
self.skin = random.choice(skins["normal"])
if random.randint(1,10)==1: # 1/10 chance to have a special
@ -28,8 +30,8 @@ class Spawner(BaseObject):
lemming.move(-lemming.rect[2]/2,-lemming.rect[3]/2)
self.game.gameloop.summon(lemming)
self.game.gameloop.delid(self.id)
self.game.globals["scamerax"]+=3
self.game.globals["scameray"]+=3
self.game.globals["scamerax"]+=2
self.game.globals["scameray"]+=2
# Spawn dust particles
sprites = self.game.getSpriteDir("particles/dust/")

View File

@ -0,0 +1,15 @@
from gamedata.objects.button import Button
class Reset(Button):
def __init__(self,x,y,game,w,h):
super().__init__(x,y,game,w,h)
self.text = "Reset save"
def reset(self,game):
game.globals["highscore"] = 0
game.scene = game.scenes.main
self.click = reset

View File

@ -9,6 +9,7 @@ from gamedata.objects.ingame.manager import Manager
from gamedata.objects.gameover import GameOver
from gamedata.objects.ingame.skies import Skies
from gamedata.objects.ingame.clouds import Clouds
from gamedata.objects.resetbutton import Reset
def main(game):
game.scaleCamera()
@ -38,9 +39,11 @@ def options(game):
game.globals["cameray"] = 0
s = BGMSlider(40,40,game,400,40)
s2 = SFXSlider(40,100,game,400,40)
btn = Reset(40,160 ,game,400,40)
menu = OptionMenu(round(game.DISPLAY_WIDTH/8),round(game.DISPLAY_HEIGHT*9/10),game,round(game.DISPLAY_WIDTH*6/8),round(game.DISPLAY_HEIGHT/10-game.DISPLAY_HEIGHT/30))
game.gameloop.summon(s)
game.gameloop.summon(s2)
game.gameloop.summon(btn)
game.gameloop.summon(menu)
def gameover(game):