diff --git a/gamedata/assets/fontmap.png b/gamedata/assets/fontmap.png index 9e8f840..05b8a0b 100644 Binary files a/gamedata/assets/fontmap.png and b/gamedata/assets/fontmap.png differ diff --git a/gamedata/assets/medals/clock.png b/gamedata/assets/medals/clock.png new file mode 100644 index 0000000..83521e7 Binary files /dev/null and b/gamedata/assets/medals/clock.png differ diff --git a/gamedata/assets/medals/clockoff.png b/gamedata/assets/medals/clockoff.png new file mode 100644 index 0000000..099cdf5 Binary files /dev/null and b/gamedata/assets/medals/clockoff.png differ diff --git a/gamedata/assets/medals/wave.png b/gamedata/assets/medals/wave.png new file mode 100644 index 0000000..db124bd Binary files /dev/null and b/gamedata/assets/medals/wave.png differ diff --git a/gamedata/assets/medals/waveoff.png b/gamedata/assets/medals/waveoff.png new file mode 100644 index 0000000..538ba93 Binary files /dev/null and b/gamedata/assets/medals/waveoff.png differ diff --git a/gamedata/assets/trash.png b/gamedata/assets/trash.png new file mode 100644 index 0000000..7d0e318 Binary files /dev/null and b/gamedata/assets/trash.png differ diff --git a/gamedata/game.py b/gamedata/game.py index 881dadb..8502883 100644 --- a/gamedata/game.py +++ b/gamedata/game.py @@ -95,6 +95,7 @@ class Game(): self.globals["hitpose"] = False self.globals["finishedlevels"] = [] # Levels where the player went to the end self.globals["completedlevels"] = [] # Levels where the player kicked all non-respawnable ennemies + self.globals["speedrunlevels"] = [] # Levels where the player finished fast enough self.globals["allunlocked"] = True self.scaleCamera() @@ -289,7 +290,7 @@ class Game(): self.globals["tempsubsurface"] = pygame.Surface((neww,newh)) def getchar(self,char,width=9,height=9): - chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@\"#&()*:;?!abcdefghijklmnopqrstuvwxyz" + chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@\"#&()*:;?!abcdefghijklmnopqrstuvwxyz/" charsperline = self.fontmap.get_width()//width result = None if char in chars: diff --git a/gamedata/maps/Level 1/map.json b/gamedata/maps/Level 1/map.json index f3e2170..57344ee 100644 --- a/gamedata/maps/Level 1/map.json +++ b/gamedata/maps/Level 1/map.json @@ -1704,6 +1704,7 @@ [1, 0], [1, 0], [1, 0], + [1, 0], [2, 0], [-1], [-1], @@ -1734,7 +1735,6 @@ [-1], [-1], [-1], - [-1], [10, 6], [9, 6], [10, 6], @@ -1881,6 +1881,7 @@ [1, 1], [3, 0], [1, 2], + [1, 2], [2, 2], [-1], [-1], @@ -1911,7 +1912,6 @@ [-1], [-1], [-1], - [-1], [10, 7], [9, 7], [10, 7], @@ -6095,7 +6095,7 @@ {"name": "Solid", "id": 31, "_eid": "17026310", "x": 1056, "y": 208, "width": 80, "height": 64, "originX": 0, "originY": 0}, {"name": "Solid", "id": 32, "_eid": "17026310", "x": 1136, "y": 192, "width": 64, "height": 80, "originX": 0, "originY": 0}, {"name": "Solid", "id": 33, "_eid": "17026310", "x": 1232, "y": 176, "width": 96, "height": 16, "originX": 0, "originY": 0}, - {"name": "Solid", "id": 34, "_eid": "17026310", "x": 1360, "y": 144, "width": 160, "height": 32, "originX": 0, "originY": 0}, + {"name": "Solid", "id": 34, "_eid": "17026310", "x": 1360, "y": 144, "width": 176, "height": 32, "originX": 0, "originY": 0}, {"name": "Solid", "id": 35, "_eid": "17026310", "x": 1392, "y": 176, "width": 96, "height": 16, "originX": 0, "originY": 0}, {"name": "Solid", "id": 36, "_eid": "17026310", "x": 1584, "y": 224, "width": 80, "height": 48, "originX": 0, "originY": 0}, {"name": "Solid", "id": 37, "_eid": "17026310", "x": 1664, "y": 208, "width": 48, "height": 64, "originX": 0, "originY": 0}, @@ -6335,7 +6335,10 @@ {"x": 2448, "y": 288} ], "values": {"Speed": 3} - } + }, + {"name": "TrashBag", "id": 30, "_eid": "74601465", "x": 1680, "y": 192, "originX": 0, "originY": 0}, + {"name": "TrashBag", "id": 31, "_eid": "74601465", "x": 1456, "y": 224, "originX": 0, "originY": 0}, + {"name": "TrashBag", "id": 32, "_eid": "74601465", "x": 1088, "y": 192, "originX": 0, "originY": 0} ] } ] diff --git a/gamedata/maps/Overworld/map.json b/gamedata/maps/Overworld/map.json index aa43faf..a9b8e56 100644 --- a/gamedata/maps/Overworld/map.json +++ b/gamedata/maps/Overworld/map.json @@ -1583,7 +1583,7 @@ {"x": 512, "y": 96}, {"x": 640, "y": 144} ], - "values": {"0": "Beginning", "1": "The Docks"} + "values": {"0": "Beginning;20", "1": "The Docks;40"} } ] } diff --git a/gamedata/maps/Overworld/overworldtiles.png b/gamedata/maps/Overworld/overworldtiles.png index 4d3ccf9..74d1012 100644 Binary files a/gamedata/maps/Overworld/overworldtiles.png and b/gamedata/maps/Overworld/overworldtiles.png differ diff --git a/gamedata/objects/ingame/endflag.py b/gamedata/objects/ingame/endflag.py index c356f05..5f267da 100644 --- a/gamedata/objects/ingame/endflag.py +++ b/gamedata/objects/ingame/endflag.py @@ -1,5 +1,5 @@ from gamedata.objects.ingame.ennemies.ennemy import Ennemy -from gamedata.objects.transition import Transition +from gamedata.objects.results import Results class EndFlag(Ennemy): @@ -54,12 +54,18 @@ class EndFlag(Ennemy): self.game.addParticle(sprites,self.rect.center[0]+offsetx,self.rect.center[1]+offsety,velx=velx,vely=vely,modvely=0.1,fps=2) if not self.game.globals["levelname"] in self.game.globals["finishedlevels"]: self.game.globals["finishedlevels"].append(self.game.globals["levelname"]) + if self.game.globals["totaltrashes"]==self.game.globals["trashes"]: + if not self.game.globals["levelname"] in self.game.globals["completedlevels"]: + self.game.globals["completedlevels"].append(self.game.globals["levelname"]) + if int(self.game.globals["timetobeat"])>=int(self.game.globals["timer"]): + if not self.game.globals["levelname"] in self.game.globals["speedrunlevels"]: + self.game.globals["speedrunlevels"].append(self.game.globals["levelname"]) self.sfx.play() if self.ended: - if self.endtimer.tick(self.game.dt): - t = Transition(self.game) - self.game.gameloop.summon(t) + if self.endtimer.tick(self.game.dt) and self.endtimer.getloops()<2: + r = Results(self.game) + self.game.gameloop.summon(r) def draw(self): sprite = self.sprites[int(self.spriteindex)%len(self.sprites)] diff --git a/gamedata/objects/ingame/ennemies/ennemy.py b/gamedata/objects/ingame/ennemies/ennemy.py index 42c2807..5f402d9 100644 --- a/gamedata/objects/ingame/ennemies/ennemy.py +++ b/gamedata/objects/ingame/ennemies/ennemy.py @@ -25,6 +25,9 @@ class Ennemy(Movable): self.dustparticles = game.getSpriteDir("particles/dust/") + def deadtrigger(self): + pass + def step(self): if not self.dead: @@ -45,6 +48,7 @@ class Ennemy(Movable): if self.rect.colliderect(self.player.hitrect): # Die self.dead = True + self.deadtrigger() # Add particles self.game.addParticle(self.dustparticles,self.rect.center[0]+self.particleoffsetx,self.rect.center[1]+self.particleoffsety) # Dust self.game.addParticle([self.deadsprite],self.rect.center[0]+self.particleoffsetx,self.rect.center[1]+self.particleoffsety,fps=0.6,vely=-1.5,modvely=0.15) # Die sprite diff --git a/gamedata/objects/ingame/ennemies/robot.py b/gamedata/objects/ingame/ennemies/robot.py index 17635ca..ceccfdc 100644 --- a/gamedata/objects/ingame/ennemies/robot.py +++ b/gamedata/objects/ingame/ennemies/robot.py @@ -16,6 +16,8 @@ class Robot(Ennemy): self.falling = 20 self.spriteindex = 0 + self.respawn = False + self.gravityway = 1 # Vertical flip self.walkingway = 1 # Horizontal flip @@ -29,6 +31,11 @@ class Robot(Ennemy): else: self.endpoints = None + self.game.globals["totaltrashes"]+=1 + + def deadtrigger(self): + self.game.globals["trashes"]+=1 + def step(self): if not self.dead: diff --git a/gamedata/objects/ingame/ennemies/trashbag.py b/gamedata/objects/ingame/ennemies/trashbag.py new file mode 100644 index 0000000..442bd52 --- /dev/null +++ b/gamedata/objects/ingame/ennemies/trashbag.py @@ -0,0 +1,20 @@ +from gamedata.objects.ingame.ennemies.ennemy import Ennemy + +class TrashBag(Ennemy): + + def __init__(self,*args): + + super().__init__(*args) + + self.sprite = self.game.sprite_lib["trash.png"] + self.deadsprite = self.sprite + + self.rect[2],self.rect[3] = self.sprite.get_size() + + self.respawn = False + self.canhit = False + + self.game.globals["totaltrashes"]+=1 + + def deadtrigger(self): + self.game.globals["trashes"]+=1 diff --git a/gamedata/objects/ingame/player.py b/gamedata/objects/ingame/player.py index f8e2790..d955713 100644 --- a/gamedata/objects/ingame/player.py +++ b/gamedata/objects/ingame/player.py @@ -132,6 +132,7 @@ class Player(Movable): if canmove: if self.canmove: self.horspd=(keys["right"]["pressed"]-keys["left"]["pressed"])*self.game.dt*self.speed + self.game.globals["timer"]+=self.game.dt if self.landingtimer<=0: self.sprite = self.spritestill @@ -293,9 +294,9 @@ class Player(Movable): self.horkb = hor self.verkb = ver self.canfastfall = True - self.game.globals["scamerax"] = 4 - self.game.globals["scameray"] = 4 if resetcombo: + self.game.globals["scamerax"] = 4 + self.game.globals["scameray"] = 4 self.combo = 0 self.hurtsfx.play() self.hp-=1 @@ -309,7 +310,7 @@ class Player(Movable): self.rect[2],self.rect[3] = 0,0 self.dead = True - t = Transition(self.game,time=1,holdtime=0.5,level=self.game.globals["levelname"]) + t = Transition(self.game,time=1,holdtime=0.5,level="Level "+str(self.game.globals["levelname"]+1)) self.game.gameloop.summon(t) self.game.addParticle([self.spritehurt],self.rect.center[0],self.rect.center[1],fps=0.6,vely=-1.5,modvely=0.15) # Die sprite diff --git a/gamedata/objects/ingame/tileset.py b/gamedata/objects/ingame/tileset.py index 15d87a0..be9ce87 100644 --- a/gamedata/objects/ingame/tileset.py +++ b/gamedata/objects/ingame/tileset.py @@ -4,6 +4,7 @@ from gamedata.objects.ingame.ennemies.crate import Crate from gamedata.objects.ingame.ennemies.balloon import Balloon from gamedata.objects.ingame.ennemies.spring import Spring from gamedata.objects.ingame.ennemies.waterchange import WaterChange +from gamedata.objects.ingame.ennemies.trashbag import TrashBag from gamedata.objects.ingame.endflag import EndFlag from gamedata.objects.levels import Levels @@ -20,6 +21,10 @@ class TilesetRenderer(BaseObject): self.level = game.levels_lib[mapfoldername] self.reinit(self.level) + self.game.globals["totaltrashes"] = 0 + self.game.globals["trashes"] = 0 + self.game.globals["timer"] = 0 + self.bgs = [game.sprite_lib["fallbackground.png"]] if len(self.level["backgrounds"]): self.bgs = self.level["backgrounds"] @@ -72,7 +77,7 @@ class TilesetRenderer(BaseObject): self.layers = [] self.spawns = [] spawnlists = {"Spawns":self.spawns} - ennemies = {"Robot":Robot,"Crate":Crate,"Balloon":Balloon,"Spring":Spring,"WaterChange":WaterChange,"Levels":Levels,"End":EndFlag} + ennemies = {"Robot":Robot,"Crate":Crate,"Balloon":Balloon,"Spring":Spring,"WaterChange":WaterChange,"Levels":Levels,"End":EndFlag,"TrashBag":TrashBag} self.queue = [] # For spawning ennemies after beeing initialized if "layers" in json.keys() and type(json["layers"]).__name__=="list": solidlayer = False diff --git a/gamedata/objects/levels.py b/gamedata/objects/levels.py index 0d30264..317e756 100644 --- a/gamedata/objects/levels.py +++ b/gamedata/objects/levels.py @@ -17,6 +17,11 @@ class Levels(BaseObject): self.playerwalking = self.game.getSpriteDir("player/walking/") self.playerstill = self.game.sprite_lib["player/still.png"] + self.medalwave = self.game.sprite_lib["medals/wave.png"] + self.medalwaveoff = self.game.sprite_lib["medals/waveoff.png"] + self.medalclock = self.game.sprite_lib["medals/clock.png"] + self.medalclockoff = self.game.sprite_lib["medals/clockoff.png"] + self.flip = False self.moving = False self.spriteindex = 0 @@ -28,14 +33,14 @@ class Levels(BaseObject): v["x"]+=8 # Center on tiles v["y"]+=8 self.flagsindex.append(self.game.lib.randint(1,3)) - + # Get sprites for "Level N" sprite = self.game.getchars("Level "+str(i+1)) self.textnumbers.append(sprite) # Get sprites for the level's name if str(i) in customvalues.keys(): - sprites = self.game.getchars(customvalues[str(i)]) + sprites = self.game.getchars(customvalues[str(i)].split(";")[0]) self.names.append(sprites) else: self.names.append(None) @@ -64,7 +69,13 @@ class Levels(BaseObject): # Launch the level t = Transition(self.game,level = "Level "+str(self.cursor+1)) self.launched = True - self.game.globals["levelname"] = "Level "+str(self.cursor+1) + self.game.globals["levelname"] = self.cursor + if str(self.cursor) in self.customvalues.keys(): + props = self.customvalues[str(self.cursor)].split(";") + self.game.globals["levellore"] = props[0] + self.game.globals["timetobeat"] = props[1] + else: + self.game.globals["levellore"] = None self.game.gameloop.summon(t) self.cursor = min(self.cursor,len(self.nodes)-1) self.cursor = max(0,self.cursor) @@ -87,7 +98,7 @@ class Levels(BaseObject): def draw(self): for i,v in enumerate(self.nodes): # Draw flags sprites = self.blueflags - if "Level "+str(i+1) in self.game.globals["finishedlevels"]: + if i in self.game.globals["finishedlevels"]: sprites = self.greenflags sprite = sprites[int(self.flagsindex[i])%len(sprites)] x = v["x"]-sprite.get_width()/2-self.game.globals["camerax"]+8 @@ -110,6 +121,19 @@ class Levels(BaseObject): x = self.nodes[self.cursor]["x"]-self.game.globals["camerax"]-sprite.get_width()/2 y = self.nodes[self.cursor]["y"]-self.game.globals["cameray"]-sprite.get_height()/2-50 self.game.window.blit(sprite,[x,y]) + # Medals + wave = self.medalwaveoff + if self.cursor in self.game.globals["completedlevels"]: + wave = self.medalwave + clock = self.medalclockoff + if self.cursor in self.game.globals["speedrunlevels"]: + clock = self.medalclock + + x = self.nodes[self.cursor]["x"]-self.game.globals["camerax"] + y = self.nodes[self.cursor]["y"]-72 + self.game.window.blit(wave,[x-wave.get_width()-1,y]) + self.game.window.blit(clock,[x+1,y]) + # Draw the level's name if self.names[self.cursor]: sprite = self.names[self.cursor] diff --git a/gamedata/objects/results.py b/gamedata/objects/results.py new file mode 100644 index 0000000..907a92d --- /dev/null +++ b/gamedata/objects/results.py @@ -0,0 +1,78 @@ +from gamedata.objects.base import BaseObject +from gamedata.objects.transition import Transition + +class Results(BaseObject): + + def __init__(self,game): + + super().__init__(0,0,game) + + self.maxcount = self.game.globals["totaltrashes"] + self.currentcount = 0 + self.count = self.game.globals["trashes"] + self.text = self.game.getchars("Cleared : 0 / "+str(self.maxcount)) + self.levelname = self.game.getchars("Level "+str(self.game.globals["levelname"]+1)) + self.levellore = None + txt = "Time : "+str(int(self.game.globals["timer"])) + txt += " ( "+str(self.game.globals["timetobeat"])+" for medal )" + self.seconds = self.game.getchars(txt) + if self.game.globals["levellore"]: + self.levellore = self.game.getchars(self.game.globals["levellore"]) + + self.fill = self.game.pygame.Surface((self.game.globals["cameraw"],self.game.globals["camerah"])) + self.fill.fill([62,33,55]) + + self.fadetimer = self.game.lib.Timer(2) + self.faded = False + self.alphamax = 200 + self.alpha = 0 + + self.medalwave = self.game.sprite_lib["medals/wave.png"] + self.medalclock= self.game.sprite_lib["medals/clock.png"] + + self.transition = False + + self.depth = 3 + + def step(self): + + past = int(self.currentcount) + self.currentcount+=self.game.dt + self.currentcount += (self.count - self.currentcount)*self.game.dt + self.currentcount = min(self.currentcount,self.count) + + if int(self.currentcount)>past: + # Make a noise + self.text = self.game.getchars("Cleared : "+str(int(self.currentcount))+" / "+str(self.maxcount)) + + if not self.transition: + keys = ["up","down","left","right"] + for i in keys: + self.transition = self.transition or self.game.inputs["keys"][i]["timer"]==1 + if self.transition: + t = Transition(self.game) + self.game.gameloop.summon(t) + + if not self.faded: + self.alpha = (1-self.fadetimer.getratio())*self.alphamax + if self.fadetimer.tick(self.game.dt): + self.faded = True + else: + self.alpha = self.alphamax + + def draw(self): + self.fill.set_alpha(self.alpha) + self.game.window.blit(self.fill,[0,0]) + cx = self.game.globals["cameraw"]/2 + cy = self.game.globals["camerah"]/2 + + self.game.lib.drawcenter(self.game,self.levelname,cx,cy-50) # Level names + if self.levellore: + self.game.lib.drawcenter(self.game,self.levellore,cx,cy-39) + + self.game.lib.drawcenter(self.game,self.text,cx,cy) # Clean + self.game.lib.drawcenter(self.game,self.seconds,cx,cy+20) + if self.currentcount == self.maxcount: # Medals + self.game.lib.drawcenter(self.game,self.medalwave,cx+150,cy) + if int(self.game.globals["timetobeat"]) >= int(self.game.globals["timer"]): + self.game.lib.drawcenter(self.game,self.medalclock,cx+150,cy+20) diff --git a/gamedata/objects/transition.py b/gamedata/objects/transition.py index ba6c577..15f83d6 100644 --- a/gamedata/objects/transition.py +++ b/gamedata/objects/transition.py @@ -28,7 +28,10 @@ class Transition(BaseObject): else: if self.holdtimer.tick(self.game.dt): if self.level: - self.game.scenes.ingame(self.game,level = self.level) + if self.level!="END": + self.game.scenes.ingame(self.game,level = self.level) + else: + self.game.scenes.end(self.game) else: self.game.scenes.overworld(self.game) diff --git a/gamedata/scenes.py b/gamedata/scenes.py index a843365..abcd4bf 100644 --- a/gamedata/scenes.py +++ b/gamedata/scenes.py @@ -9,6 +9,7 @@ from gamedata.objects.ingame.manager import FightManager from gamedata.objects.ingame.hitbox import Hitbox from gamedata.objects.ingame.tileset import TilesetRenderer from gamedata.objects.ingame.water import Water +from gamedata.objects.results import Results def main(game): game.scaleCamera()