Compare commits
6 Commits
a404444f61
...
706b7e0d92
Author | SHA1 | Date |
---|---|---|
theo@manjaro | 706b7e0d92 | |
theo@manjaro | aa631c188e | |
theo@manjaro | f968827b7b | |
theo@manjaro | 74e05b11d2 | |
theo@manjaro | 693e4a49e8 | |
theo@manjaro | eca2323d1a |
|
@ -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)
|
||||
|
|
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 602 B |
After Width: | Height: | Size: 597 B |
After Width: | Height: | Size: 602 B |
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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])
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ class Skies(BaseObject):
|
|||
|
||||
self.blackrectalpha = 0.5
|
||||
|
||||
self.handlepause = True
|
||||
|
||||
def step(self):
|
||||
|
||||
self.timeelapsed+=self.game.dt
|
||||
|
|
|
@ -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/")
|
||||
|
|
|
@ -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
|
|
@ -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):
|
||||
|
|