Getting Started with 2D Games Using Pyxel (Part 7): Control the Character
Source: Dev.to
Control the Character
In this chapter we detect when the Space key is pressed and flip the player’s movement direction left ↔ right. This gives a stronger sense of direct control.
Set Initial Movement Direction
In the Game constructor we randomly choose the ship’s initial direction (right = 0° or left = 180°) and set its velocity.
# main.py – inside Game.__init__()
import random
# Randomly choose left or right
deg = 0 if random.random() < 0.5 else 180
self.ship.move(SHIP_SPD, deg)
Flip X Method
Add a flip_x() method to BaseSprite that reverses the x‑axis velocity.
# sprite.py – added to BaseSprite class
def flip_x(self):
"""Flip movement in the x direction"""
self.vx *= -1
Calling flip_x() changes the direction:
- Right → Left
- Left → Right
Handle Keyboard Input
Create a control_ship() method in the Game class. It uses pyxel.btnp() to detect the exact moment the Space key is pressed and then flips the ship’s direction.
# main.py – added to Game class
def control_ship(self):
"""Handle input"""
if pyxel.btnp(pyxel.KEY_SPACE):
self.ship.flip_x() # Reverse movement
Each press of Space toggles the ship’s horizontal movement.
Screen‑Wrap Logic
When the ship leaves the screen we move it to the opposite side. The reusable overlap_spr() method works for any sprite (e.g., future asteroids).
# main.py – added to Game class
def overlap_spr(self, spr):
"""Wrap sprite around screen edges"""
if spr.x < -spr.w:
spr.x = W
return
if W < spr.x:
spr.x = -spr.w
return
if spr.y < -spr.h:
spr.y = H
return
if H < spr.y:
spr.y = -spr.h
return
Complete Code
Below is the full implementation of the features described above.
# sprite.py
import pyxel
import math
import random
class BaseSprite:
def __init__(self, x, y, w=8, h=8):
self.x = x
self.y = y
self.w = w
self.h = h
self.vx = 0
self.vy = 0
def update(self):
self.x += self.vx
self.y += self.vy
def draw(self):
pass # Implemented in subclasses
def move(self, spd, deg):
rad = deg * math.pi / 180
self.vx = spd * math.cos(rad)
self.vy = spd * math.sin(rad)
def flip_x(self):
"""Flip movement in the x direction"""
self.vx *= -1
class ShipSprite(BaseSprite):
def __init__(self, x, y):
super().__init__(x, y)
def draw(self):
pyxel.blt(self.x, self.y, 0, 0, 0, self.w, self.h, 0)
# main.py
import pyxel
import random
import sprite
W, H = 160, 120
SHIP_SPD = 1.4 # Player speed
class Game:
def __init__(self):
self.score = 0
self.ship = sprite.ShipSprite(W / 2, H - 40)
# Random initial direction
deg = 0 if random.random() < 0.5 else 180
self.ship.move(SHIP_SPD, deg)
pyxel.init(W, H, title="Hello, Pyxel!!")
pyxel.load("shooter.pyxres")
pyxel.run(self.update, self.draw)
def update(self):
self.ship.update()
self.control_ship()
self.overlap_spr(self.ship)
def draw(self):
pyxel.cls(0)
pyxel.text(10, 10, f"SCORE:{self.score:04}", 12)
self.ship.draw()
def control_ship(self):
if pyxel.btnp(pyxel.KEY_SPACE):
self.ship.flip_x() # Reverse movement
def overlap_spr(self, spr):
if spr.x < -spr.w:
spr.x = W
return
if W < spr.x:
spr.x = -spr.w
return
if spr.y < -spr.h:
spr.y = H
return
if H < spr.y:
spr.y = -spr.h
return
def main():
Game()
if __name__ == "__main__":
main()
Running the game shows the ship moving horizontally; pressing Space flips its direction, and it wraps around the screen edges.
In the next chapter we’ll cover “Let’s Spawn Asteroids.”