Tunnel Dodge Game 1 (Sample)
In this article, we introduce a somewhat nostalgic game where you jump through gaps in tunnels.
Here, we only provide sample code.
1. Preparing the Assets
Using the Pyxel Editor, draw the assets for the player and the tunnels.
Download the resource file (Click the “Download” button in the top-right corner of the page.)
Sample Code
The sample code for this game is shown below.
# sprite.py
import pyxel
import math
import random
class BaseSprite:
def __init__(self, x, y, w=8, h=8):
""" Constructor """
self.x = x
self.y = y
self.w = w
self.h = h
self.vx = 0
self.vy = 0
def update(self):
""" Update process """
self.x += self.vx
self.y += self.vy
def draw(self):
""" Draw process (implemented in subclasses) """
pass
def move(self, spd, deg):
""" Move sprite """
rad = deg * math.pi / 180
self.vx = spd * math.cos(rad) # Velocity in x direction
self.vy = spd * math.sin(rad) # Velocity in y direction
def intersects(self, other):
""" AABB collision detection """
if other.x + other.w < self.x:
return False
if self.x + self.w < other.x:
return False
if other.y + other.h < self.y:
return False
if self.y + self.h < other.y:
return False
return True
class PlayerSprite(BaseSprite):
def __init__(self, x, y):
""" Constructor """
super().__init__(x, y)
self.gravity = 0.4 # Gravity
self.jump_x = 1.0 # Jump velocity (x)
self.jump_y = -3.4 # Jump velocity (y)
def update(self):
""" Update process """
super().update()
self.vy += self.gravity # Apply gravity
def draw(self):
""" Draw process """
pyxel.blt(
self.x, self.y, 0,
0, 16, self.w, self.h, 0
)
# Debug
# pyxel.rectb(self.x, self.y, self.w, self.h, 3)
def jump(self):
""" Jump """
self.vx = self.jump_x
self.vy = self.jump_y
class TunnelSprite(BaseSprite):
def __init__(self, x, y, length, top_flg=False):
""" Constructor """
super().__init__(x, y, 16, length * 8)
self.length = length # Tunnel length
if top_flg:
self.y -= self.h # Upper tunnel
def draw(self):
""" Draw process """
# Top
pyxel.blt(
self.x, self.y, 0,
16, 16, self.w, 8, 0
)
# Middle
for i in range(self.length - 2):
y = self.y + (i + 1) * 8
pyxel.blt(
self.x, y, 0,
16, 24, self.w, 8, 0
)
# Bottom
y = self.y + (self.length - 1) * 8
pyxel.blt(
self.x, y, 0,
16, 32, self.w, 8, 0
)
# Debug
# pyxel.rectb(self.x, self.y, self.w, self.h, 3)
# main.py
import pyxel
import math
import random
import sprite
W, H = 120, 120
START_X = W / 3
START_Y = H / 2 - 12
MODE_TITLE = "title"
MODE_PLAY = "play"
MODE_GAME_OVER = "game_over"
class Game:
def __init__(self):
""" Constructor """
# Initialize score
self.score = 0
# Game mode
self.game_mode = MODE_TITLE
# Initialize player
self.player = sprite.PlayerSprite(START_X, START_Y)
# Initialize stage
self.reset()
# Initialize Pyxel
pyxel.init(W, H, title="Hello, Pyxel!!")
pyxel.load("shooter.pyxres")
pyxel.run(self.update, self.draw)
def update(self):
""" Update process """
# Update score
self.score = int(self.player.x - START_X)
# Control input
self.control()
# Only update during play mode
if self.game_mode != MODE_PLAY:
return
# Update player
self.player.update()
# Update tunnels
for tunnel in self.tunnels:
tunnel.update()
if tunnel.intersects(self.player):
self.game_mode = MODE_GAME_OVER
break
# Falling check
if H < self.player.y:
self.game_mode = MODE_GAME_OVER
def draw(self):
""" Draw process """
pyxel.cls(0)
# Camera (set)
pyxel.camera(self.player.x - START_X, 0)
# Draw player
self.player.draw()
# Draw tunnels
for tunnel in self.tunnels:
tunnel.draw()
# Camera (reset)
pyxel.camera()
# Messages
if self.game_mode == MODE_TITLE:
msg = "SPACE TO PLAY"
pyxel.text(W / 2 - len(msg) * 2, H / 2, msg, 13)
elif self.game_mode == MODE_GAME_OVER:
msg = "GAME OVER"
pyxel.text(W / 2 - len(msg) * 2, H / 2, msg, 13)
# Draw score
pyxel.text(
10, 10,
"SCORE:{:04}".format(self.score), 12
)
def reset(self):
""" Reset stage """
# Player
self.player.x = START_X
self.player.y = START_Y
# Tunnels
self.tunnels = []
for i in range(24):
pad_x = 42
pad_y = random.randint(2, 3) * 8
x = START_X + pad_x * i + 24
y = H / 2 + random.randint(-2, 2) * 8
t_top = sprite.TunnelSprite(x, y - pad_y, 10, True)
self.tunnels.append(t_top)
t_bottom = sprite.TunnelSprite(x, y + pad_y, 10)
self.tunnels.append(t_bottom)
def control(self):
""" Control """
if not pyxel.btnp(pyxel.KEY_SPACE):
return
# Title -> Play
if self.game_mode == MODE_TITLE:
self.game_mode = MODE_PLAY
# Game Over -> Title
if self.game_mode == MODE_GAME_OVER:
self.game_mode = MODE_TITLE
self.reset()
# Jump
if self.game_mode == MODE_PLAY:
self.player.jump()
def main():
""" Main process """
Game()
if __name__ == "__main__":
main()
Result
When you run the game, it will look like this.
Final Words
Thank you very much for reading until the end.
I hope this series becomes a starting point for your game development journey.
If you enjoyed it, a 👍 would be greatly appreciated!


Top comments (0)