10 Commits

Author SHA1 Message Date
Neal Finger
bcd3715a9e Merge branch 'master' into title_screen 2023-02-05 16:16:09 -07:00
Neal Finger
6c05beaba0 thing
desc
2023-02-05 16:14:45 -07:00
William Hubbard
77fd56b7b8 Merge branch 'master' into collectibles 2023-02-05 16:10:55 -07:00
William Hubbard
8aab7d94f1 Adds a sky. 2023-02-05 16:10:11 -07:00
Neal Finger
5acb279226 title screen
sprite, player root animation calm down
2023-02-05 15:59:55 -07:00
William Hubbard
51be611e2f Merge pull request #11 from Markil3/collectibles
Collectibles
2023-02-05 15:57:53 -07:00
William Hubbard
3afe5322b3 Adds a seed entity.
Graphics!
2023-02-05 15:57:11 -07:00
William Hubbard
674ae01057 Adds collectibles and fixes score 2023-02-05 15:50:20 -07:00
William Hubbard
feafdfbac2 Implements scaling difficulty.
Probably not balanced, but it is there.
2023-02-05 15:19:16 -07:00
Neal Finger
b743e61b10 Merge pull request #10 from Markil3/build_update_finalish
general update
2023-02-05 14:59:45 -07:00
7 changed files with 133 additions and 65 deletions

View File

@@ -11,7 +11,7 @@ from random import randrange
from Games.Throot.artrepository import * from Games.Throot.artrepository import *
from Games.Throot.player import Player, Camera from Games.Throot.player import Player, Camera
from Games.Throot.map import ObstacleSlice, OBSTACLE_SLICES from Games.Throot.map import ObstacleSlice, OBSTACLE_SLICES
from Games.Throot.sprites import Obstacle, update_entities from Games.Throot.sprites import Entity, Obstacle, Collectible, update_entities
from Games.Throot.constants import * from Games.Throot.constants import *
@@ -46,6 +46,9 @@ class GameManager:
class Room: class Room:
def __init__(self):
self.ind_button = 0
def start(self, event): def start(self, event):
t0 = time.ticks_ms() # Get time (ms) t0 = time.ticks_ms() # Get time (ms)
thumby.display.fill(0) # Fill canvas to black thumby.display.fill(0) # Fill canvas to black
@@ -64,17 +67,37 @@ class RoomTitle(Room):
} }
# draw title sprite # draw title sprite
title_text = 'press a to start' #thumby.display.drawSprite(sprite_title.width, sprite_title.height, sprite_title.image)
chr_len = 5 thumby.display.blit(sprite_title.image, 0, 0, sprite_title.width, sprite_title.height,
x = int(round(thumby.display.width / 2 - (chr_len * len(title_text)) / 2)) -1, 0, 0)
y = int(round(thumby.display.height / 2 - chr_len / 2))
# title text
chrx = 5
chry = 7
buff = 2 buff = 2
w = chr_len * len(title_text) + buff
h = chr_len + buff x = 14#int(round(thumby.display.width / 2 - (chr_len * len(title_text)) / 2))
thumby.display.drawFilledRectangle(x - buff, y - buff, w, h, 1) y = 40 - chry - buff#int(round(thumby.display.height / 2 - chr_len / 2))
thumby.display.drawText(title_text, x, y, 0)
w = chrx * 6 + buff
h = chry + buff
thumby.display.drawFilledRectangle(x - buff, y - buff, w, h * 2 + buff, 0)
#thumby.display.drawText('press a', x, y, 0)
thumby.display.drawText('start', x, y, 1)
spr_b = thumby.Sprite(sprite_buttona1.width, sprite_buttona1.height, sprite_buttona1.image + sprite_buttona2.image, 2, 40 - 8,
-1, 0, 0)
# thumby.display.blit(sprite_buttona.image, 2, 40 - 8, sprite_buttona.width, sprite_buttona.height,
# -1, 0, 0)
self.ind_button = (self.ind_button + 1) % (2 * CONST_FPS)
spr_b.setFrame(self.ind_button // (2 * CONST_FPS))
#print(self.ind_button // CONST_FPS)
thumby.display.drawSprite(spr_b)
class GameLoop(Room): class GameLoop(Room):
def __init__(self): def __init__(self):
@@ -92,12 +115,19 @@ class GameLoop(Room):
self.waterx = float(0) self.waterx = float(0)
seed_sprite = thumby.Sprite(seed.width, seed.height, seed.image, 0, 0, 0, False, False)
self.seed = Entity((thumby.display.width - seed.width) // 2, 0, seed.width, seed.height, None, seed_sprite)
def start(self, event): def start(self, event):
self.entities.clear() self.entities.clear()
self.entities.add(
self.seed
)
self.current_obstacle_slice = OBSTACLE_SLICES[0] self.current_obstacle_slice = OBSTACLE_SLICES[0]
self.player = Player() self.player = Player()
self.player.yspeed = 10 self.player.yspeed = 10
self.score = 0 self.score = 'score' in event and event['score'] or 0
self.level = 'level' in event and event['level'] or 0
self.finish_depth = 100 + 5 * self.level ** 2 self.finish_depth = 100 + 5 * self.level ** 2
self.camera = Camera(self.player) self.camera = Camera(self.player)
@@ -105,6 +135,22 @@ class GameLoop(Room):
def get_obstacle_slice(self): def get_obstacle_slice(self):
return OBSTACLE_SLICES[randrange(0, len(OBSTACLE_SLICES))] return OBSTACLE_SLICES[randrange(0, len(OBSTACLE_SLICES))]
def draw_sky(self):
sky_x = 0
sky_y = -thumby.display.height
sky_width = thumby.display.width
sky_height = thumby.display.height
if self.camera.entity_in_camera(sky_x, sky_y, sky_width, sky_height):
sky_x, sky_y = self.camera.relative_to_camera(sky_x, sky_y)
thumby.display.drawFilledRectangle(int(sky_x), int(sky_y), int(sky_width), int(sky_height), 1)
sky_x = 0
sky_y = 0
sky_width = thumby.display.width
sky_height = thumby.display.height
if self.camera.entity_in_camera(sky_x, sky_y, sky_width, sky_height):
sky_x, sky_y = self.camera.relative_to_camera(sky_x, sky_y)
thumby.display.drawFilledRectangle(int(sky_x), int(sky_y), int(sky_width), int(sky_height), 0)
def draw_water(self): def draw_water(self):
# bookwater # bookwater
@@ -161,7 +207,7 @@ class GameLoop(Room):
# Generate new entities as needed # Generate new entities as needed
if abs(self.player.y) < abs(self.finish_depth): if abs(self.player.y) < abs(self.finish_depth):
self.entities |= update_entities(self.entities, 5, self.player.ysub, self.player.prev_y) self.entities |= update_entities(self.entities, self.level, self.player.ysub, self.player.prev_y)
else: else:
self.entities.clear() self.entities.clear()
@@ -177,17 +223,24 @@ class GameLoop(Room):
'score': self.score, 'score': self.score,
'level': self.level + 1 'level': self.level + 1
} }
elif isinstance(entity, Collectible):
self.score += entity.score
to_remove.add(entity)
self.entities -= to_remove self.entities -= to_remove
self.score = int(abs(self.player.y) * 10) self.score += int(abs(self.player.ysub - self.player.prev_y) * 10)
# finish level # finish level
if self.player.y > self.finish_depth + int(thumby.display.height * 1.5): if self.player.y > self.finish_depth + int(thumby.display.height * 1.5):
self.score += 20
self.level += 1 self.level += 1
self.start({}) self.start({
'score': self.score,
'level': self.level
})
thumby.display.fill(0) thumby.display.fill(0)
self.draw_sky()
# Draw the entities # Draw the entities
for entity in self.entities: for entity in self.entities:
entity.render(tpf, self.camera) entity.render(tpf, self.camera)

BIN
ThrootTitle.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
ThrootTitleSingleFrame.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -2,6 +2,27 @@ from collections import namedtuple
SpriteImage = namedtuple("SpriteImage", ["image", "collision", "width", "height"]) SpriteImage = namedtuple("SpriteImage", ["image", "collision", "width", "height"])
seed = SpriteImage(
bytearray([8,20,46,46,62,62,46,62,46,12,0]),
None,
11,
7
)
collectibleover = SpriteImage(
bytearray([9,4,6,9]),
None,
4,
4
)
collectibleunder = SpriteImage(
bytearray([6,11,9,6]),
None,
4,
4
)
# BITMAP: width: 8, height: 8 # BITMAP: width: 8, height: 8
skull = SpriteImage( skull = SpriteImage(
bytearray([0,28,102,126,38,30,28,0]), bytearray([0,28,102,126,38,30,28,0]),
@@ -182,4 +203,25 @@ sprite_water = SpriteImage(
8 8
) )
sprite_title = SpriteImage(
bytearray([32,128,40,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0,0,0,0,0,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,160,128,32,0,72,0,192,96,24,8,4,6,2,2,2,2,2,4,12,24,112,192,0,0,0,3,3,3,3,3,255,255,255,3,251,251,251,3,3,251,251,251,3,251,251,155,155,155,155,99,99,0,248,248,24,24,24,251,251,3,251,251,27,27,27,251,251,3,255,255,255,3,3,3,0,1,0,31,48,96,64,64,64,98,50,30,0,0,192,96,48,16,24,15,12,24,48,96,192,0,0,0,255,255,255,0,255,255,255,7,7,255,255,255,0,255,255,1,1,1,3,255,255,0,255,255,128,128,128,255,255,0,255,255,128,128,128,255,255,0,255,255,255,0,0,0,0,192,64,96,32,32,69,192,10,0,4,0,0,127,129,0,0,0,0,0,0,0,96,48,29,7,0,0,63,255,255,192,149,85,85,84,84,85,85,85,84,85,85,84,84,84,84,85,85,84,85,85,85,85,85,85,85,84,85,85,85,85,85,85,21,192,255,255,127,0,0,0,3,7,4,132,128,192,96,29,70,0,0,0,0,0,1,6,12,8,24,16,248,140,4,4,108,72,120,48,0,128,193,255,255,127,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,252,254,255,183,99,65,64,64,96,48,24,30,99,65,64,194,128,133,0,2,0,128,96,24,12,4,2,2,1,1]),
None,
72,
40
)
sprite_buttona1 = SpriteImage(
bytearray([60,98,221,203,203,221,98,60]),
None,
8,
8
)
sprite_buttona2 = SpriteImage(
bytearray([56,68,186,150,150,186,68,56]),
None,
8,
8
)
OBSTACLES = [skull, pizza, boulder, ball, steve, mathroot, leaf, robot, dinoskull, dinojaw, dinospine, bone, bigdinohead, bigboneddiag, bigdoritoobstacle, spaceinv,annoydead,lvl4wall,ballobstaclelvl3,Doritoobstaclelvl5] OBSTACLES = [skull, pizza, boulder, ball, steve, mathroot, leaf, robot, dinoskull, dinojaw, dinospine, bone, bigdinohead, bigboneddiag, bigdoritoobstacle, spaceinv,annoydead,lvl4wall,ballobstaclelvl3,Doritoobstaclelvl5]

View File

@@ -4,3 +4,4 @@ ROOM_START = 0
ROOM_MAIN = 1 ROOM_MAIN = 1
ROOM_END = 2 ROOM_END = 2
ROOM_NEXT = -1 ROOM_NEXT = -1

View File

@@ -103,8 +103,8 @@ class Camera:
class PlayerAnimation: class PlayerAnimation:
# width and height of range bounding box # width and height of range bounding box must be odd
RANDOM_RANGE = int(7) RANDOM_RANGE = int(5)
POS_RANGE = int(3) POS_RANGE = int(3)
POS_X = int(0) POS_X = int(0)
POS_Y = int(1) POS_Y = int(1)
@@ -116,49 +116,12 @@ class PlayerAnimation:
def update_phys(self, plworldx, plworldy, camera): def update_phys(self, plworldx, plworldy, camera):
#print(plworldx, plworldy, plscreeny, current_depth)
### exit if player y pos less than random range
# # debug change random range
# inp = int(0)
# if thumby.buttonD.justPressed():
# inp -= 1
# if thumby.buttonU.justPressed():
# inp += 1
# if inp != 0:
# self.debugposrange = max(self.debugposrange + inp * 2, 1)
# print('debugposrange: ', self.debugposrange)
# # if plworldy < self.poslist[-1][self.POS_Y] + random.randint(1, self.debugposrange):
# # return
# if plworldy < self.poslist[-1][self.POS_Y] + self.debugposrange:
# return
if plworldy < self.poslist[-1][self.POS_Y] + self.POS_RANGE: if plworldy < self.poslist[-1][self.POS_Y] + self.POS_RANGE:
return return
### get new position ### get new position
rad = self.RANDOM_RANGE // 2 rad = self.RANDOM_RANGE // 2
# # debug change random range
# inp = int(0)
# if thumby.buttonB.justPressed():
# inp -= 1
# if thumby.buttonA.justPressed():
# inp += 1
# if inp != 0:
# self.debugrandomrange = max(self.debugrandomrange + inp * 2, 1)
# print('debugrandomrange:', self.debugrandomrange)
# rad = max(self.debugrandomrange // 2, 1)
# vector int
# self.poslist.append((plworldx + random.randrange(-rad, rad),
# plworldy + random.randrange(-rad, rad)))
# move last pos # move last pos
self.poslist[-1] = ( self.poslist[-1] = (
plworldx + random.randrange(-rad, rad), plworldx + random.randrange(-rad, rad),
@@ -168,20 +131,13 @@ class PlayerAnimation:
# new pos is perfectly on player # new pos is perfectly on player
self.poslist.append((plworldx, plworldy)) self.poslist.append((plworldx, plworldy))
# # debug
# self.poslist.append((plworldx, plworldy))
### remove the fist item in the list if its full line is off screen ### remove the fist item in the list if its full line is off screen
if not camera.entity_in_camera(self.poslist[1][self.POS_X], self.poslist[1][self.POS_Y]): if not camera.entity_in_camera(self.poslist[1][self.POS_X], self.poslist[1][self.POS_Y]):
self.poslist.pop(0) self.poslist.pop(0)
#print(len(self.poslist))
def update_draw(self, camera, isdecend=1): def update_draw(self, camera, isdecend=1):
### draw line from first position to next ### draw line from first position to next
#print(topleft)
for i in range(len(self.poslist) - 1): for i in range(len(self.poslist) - 1):
x1, y1 = camera.relative_to_camera(self.poslist[i][self.POS_X], self.poslist[i][self.POS_Y]) x1, y1 = camera.relative_to_camera(self.poslist[i][self.POS_X], self.poslist[i][self.POS_Y])
x2, y2 = camera.relative_to_camera(self.poslist[i + 1][self.POS_X], self.poslist[i + 1][self.POS_Y]) x2, y2 = camera.relative_to_camera(self.poslist[i + 1][self.POS_X], self.poslist[i + 1][self.POS_Y])

View File

@@ -5,7 +5,7 @@ import thumby
from Games.Throot.map import ObstacleSlice from Games.Throot.map import ObstacleSlice
from Games.Throot.player import Player, Camera from Games.Throot.player import Player, Camera
from Games.Throot.artrepository import OBSTACLES from Games.Throot.artrepository import *
class Entity: class Entity:
""" """
@@ -67,7 +67,7 @@ class Entity:
True if the game should keep this entity, false if the game should drop True if the game should keep this entity, false if the game should drop
this entity from memory. this entity from memory.
""" """
return False return True
def render(self, tpf: float, camera: Camera) -> bool: def render(self, tpf: float, camera: Camera) -> bool:
""" """
@@ -97,6 +97,14 @@ class Obstacle(Entity):
def update(self, tpf: float, player: Player, camera: Camera) -> bool: def update(self, tpf: float, player: Player, camera: Camera) -> bool:
return True return True
class Collectible(Entity):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.score = 'score' in kwargs and kwargs['score'] or 10
def update(self, tpf: float, player: Player, camera: Camera) -> bool:
return True
def update_entities(entities, difficulty: int, current_depth: int, prev_depth: int): def update_entities(entities, difficulty: int, current_depth: int, prev_depth: int):
""" """
@@ -125,6 +133,14 @@ def update_entities(entities, difficulty: int, current_depth: int, prev_depth: i
spawned = set() spawned = set()
max_spawned = randrange(0, difficulty + 1) max_spawned = randrange(0, difficulty + 1)
while len(spawned) < max_spawned and random() < (2 * math.pow(difficulty + 0.01, 2)) / (3 * math.pow(difficulty + 0.01, 2) + 20 * (difficulty + 0.01)) + 0.05: while len(spawned) < max_spawned and random() < (2 * math.pow(difficulty + 0.01, 2)) / (3 * math.pow(difficulty + 0.01, 2) + 20 * (difficulty + 0.01)) + 0.05:
if random() < 0.2:
Clazz = Collectible
if current_depth >= 0:
sprite_image = collectibleunder
else:
sprite_image = collectibleover
else:
Clazz = Obstacle
sprite_image = OBSTACLES[randrange(0, min((difficulty + 1) * 3, len(OBSTACLES)))] sprite_image = OBSTACLES[randrange(0, min((difficulty + 1) * 3, len(OBSTACLES)))]
if sprite_image.width >= thumby.display.width: if sprite_image.width >= thumby.display.width:
x = 0 x = 0
@@ -142,5 +158,5 @@ def update_entities(entities, difficulty: int, current_depth: int, prev_depth: i
break break
if not error: if not error:
sprite = thumby.Sprite(sprite_image.width, sprite_image.height, sprite_image.image, 0, 0, 0, False, False) sprite = thumby.Sprite(sprite_image.width, sprite_image.height, sprite_image.image, 0, 0, 0, False, False)
spawned.add(Obstacle(x, y, sprite_image.width, sprite_image.height, sprite_image.collision or sprite_image.image, sprite)) spawned.add(Clazz(x, y, sprite_image.width, sprite_image.height, sprite_image.collision or sprite_image.image, sprite))
return spawned return spawned