Tunnel Dodge Game 2 (Sample)
In this article, we introduce a sample that displays a background using a tilemap.
(This article only introduces the sample code.)
1. Preparing the Assets
Create the background assets using the Pyxel Editor.
Download the resource file
(Click the Download button at the top right to download the file.)
Sample Code
The complete sample code 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 processing """
self.x += self.vx
self.y += self.vy
def draw(self):
""" Draw processing (implemented in subclasses) """
pass
def move(self, spd, deg):
""" Move by speed and angle """
rad = deg * math.pi / 180
self.vx = spd * math.cos(rad) # Velocity on X axis
self.vy = spd * math.sin(rad) # Velocity on Y axis
def intersects(self, other):
""" Rectangle collision detection (AABB) """
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 X velocity
self.jump_y = -3.4 # Jump Y velocity
def update(self):
""" Update processing """
super().update()
self.vy += self.gravity
def draw(self):
""" Draw processing """
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 processing """
# 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 = 160, 120
START_X = W / 2 - 48
START_Y = H / 2 - 12
MODE_TITLE = "title"
MODE_PLAY = "play"
MODE_GAME_OVER = "game_over"
TUNNEL_TOTAL = 48
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()
# Start Pyxel
pyxel.init(W, H, title="Hello, Pyxel!!")
pyxel.load("flappy.pyxres")
pyxel.run(self.update, self.draw)
def update(self):
""" Update processing """
# Update score
self.score = int(self.player.x - START_X)
# Control input
self.control()
# Check play state
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 processing """
pyxel.cls(6)
# Tilemap background
pyxel.bltm(0, 0, 0, 0, 0, 192, 128, 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, 1)
elif self.game_mode == MODE_GAME_OVER:
msg = "GAME OVER"
pyxel.text(W / 2 - len(msg) * 2, H / 2, msg, 1)
# Draw score
pyxel.text(10, 10,
"SCORE:{:04}".format(self.score), 1)
def reset(self):
""" Initialize stage """
# Player position
self.player.x = START_X
self.player.y = START_Y
# Tunnels
self.tunnels = []
for i in range(TUNNEL_TOTAL):
pad_x = 42
pad_y = random.randint(2, 3) * 8
x = START_X + pad_x * i + 32
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 input """
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
The game will look like this when running.
Conclusion
Thank you very much for reading this article.
I hope this series helps you get started with game development.
(If you enjoyed it, a 👍 would be greatly appreciated!)


Top comments (0)