Skip to content

Commit

Permalink
Merge pull request #2 from DiddiLeija/v1
Browse files Browse the repository at this point in the history
[WIP] Main additions to v1
  • Loading branch information
DiddiLeija authored Nov 30, 2023
2 parents 9d1a7cc + d6bf950 commit 9bf445a
Show file tree
Hide file tree
Showing 14 changed files with 788 additions and 8 deletions.
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ko-fi: diddileija
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ htmlcov/
.coverage
.coverage.*
.cache
.ruff_cache/
nosetests.xml
coverage.xml
*.cover
Expand Down
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
# Diddi and Eli

_Diddi and Eli: a platformer game with scaling challenges._
[![Nox](https://img.shields.io/badge/%F0%9F%A6%8A-Nox-D85E00.svg)](https://github.com/wntrblm/nox)
[![License](https://img.shields.io/github/license/DiddiLeija/diddi-and-eli)](https://github.com/DiddiLeija/diddi-and-eli)
[![GitHub](https://img.shields.io/github/v/release/DiddiLeija/diddi-and-eli?logo=github&sort=semver)](https://github.com/DiddiLeija/diddi-and-eli)
[![GitHub Repo stars](https://img.shields.io/github/stars/DiddiLeija/diddi-and-eli?style=social)](https://github.com/DiddiLeija/diddi-and-eli)
[![GitHub forks](https://img.shields.io/github/forks/DiddiLeija/diddi-and-eli?style=social)](https://github.com/DiddiLeija/diddi-and-eli)

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/G2G3AL6D6)

> **Diddi and Eli: a platformer game with scaling challenges.**
## How to play

Using Python `>=3.7` and [Pyxel](https://github.com/kitao/pyxel) at a
[recommended version](./requirements.txt), clone or download this
repository and run `main.py` to start the game.

To win, you'll have to clear five courses, each one harder than the previous
one. Once you reach the final course, defeat the evil **Scaler** to win!

## Game controls

- Menu controls
- 1: Start game.
- 2: Select player mode.
- In-game controls (player 1)
- W: Jump
- A: Move to the left
- S: Shoot a bullet
- D: Move to the right
- In-game controls (player 2)
- Up key: Jump
- Left key: Move to the left
- Down key: Shoot a bullet
- Right key: Move to the right

## Credits

This game is a successor to one of my previous titles,
["Abandon the ship!"](https://github.com/DiddiLeija/abandon-the-ship), which was
based on a platformer example bundled within the [Pyxel](https://github.com/kitao/pyxel)
project.

Thanks to all those who contributed with feedback when I was developing the game.

Copyright (c) 2023 Diego Ramirez.
27 changes: 26 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,35 @@

import pyxel

from src import One, Two, Three, Four, Menu
from src import stages_list
from src.tools import init_class


class Main:
"""
Main object for the game, though most of the interface
is operated by the src-stored objects.
"""
situation = None

def __init__(self):
pyxel.load("resource.pyxres")
self.situation = init_class(stages_list["menu"], 0)
pyxel.run(self.update, self.draw)

def update(self):
self.situation.update()
# If the situation "ends", jump into the next one
# Also, keep memory of your player choice :)
if self.situation.finished:
tmp = self.situation.player_choice
self.situation = init_class(stages_list[self.situation.next], tmp)
del(tmp) # we have to remove 'tmp' ASAP

def draw(self):
self.situation.draw()


if __name__ == "__main__":
pyxel.init(128, 128, "Diddi and Eli")
Main()
26 changes: 26 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import nox

files = (
"main.py",
"noxfile.py",
"src/__init__.py",
"src/baseclasses.py",
"src/characters.py",
"src/levels.py",
"src/menu.py",
"src/tools.py"
)

@nox.session
def format(session: nox.Session):
"Format the codebase."
session.install("-r", "requirements.txt")
session.install("-r", "test-requirements.txt")
session.run("ruff", "check", *files, "--fix") # TODO: ignore certain rules?

@nox.session
def lint(session: nox.Session):
"Lint the codebase."
session.install("-r", "requirements.txt")
session.install("-r", "test-requirements.txt")
session.run("ruff", "check", *files) # TODO: ignore certain rules?
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pyxel==1.9.18
Binary file modified resource.pyxres
Binary file not shown.
27 changes: 21 additions & 6 deletions src/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
"Extra code/tools for the game."

__all__ = ("One", "Two", "Three", "Four")
from . import menu, levels

# TODO: fixme -- these four objects should be Python classes
One = None
Two = None
Three = None
Four = None
__all__ = ("stages_list")

# TODO: fixme -- these objects should be Python classes
Two = None # two.Two
Three = None # three.Three
Four = None # four.Four
Five = None # five.Five
# NOTE: Below I have the already-linked objects
Menu = menu.Menu
One = levels.One

# Below there's a dictionary with all the objects for further use
stages_list = {
"one": One,
"two": Two,
"three": Three,
"four": Four,
"five": Five,
"menu": Menu,
}
129 changes: 129 additions & 0 deletions src/baseclasses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
"Base classes used across the source code."

import pyxel

import math

from abc import ABC, abstractmethod
from .characters import *


class BaseLevel(ABC):
"Base level."
# tilemap = 0
player_choice = 0 # 0 is Diddi, 1 is Eli, and 2 is multiplayer
player = list() # Amount of players involved
finished = False # Have we finished today? Can we go home now?
next = "" # Where should we go after finishing
lost = False # Did we die??
enemy_templates = dict() # Coordinates to spawn enemies, unique for each subclass
enemies = list() # The list with enemies/mobs
draw_v = 0 # The 'v' parameter used in 'pyxel.bltm', during level drawing
music_vol = 0
SCROLL_BORDER_X = 80
scroll_x = 0

def __init__(self, player_choice):
pyxel.camera(0, self.draw_v)
self.player_choice = player_choice
self.create_characters()
self.spawn(0, 128)
pyxel.playm(self.music_vol, loop=True)

def startup(self):
# FIXME: Only use the variables stored at "src/characters",
# or only use variables from here.
self.SCROLL_BORDER_X = 80
self.scroll_x = 0
self.create_characters()
pyxel.playm(self.music_vol, loop=True)

def check_quit(self) -> None:
if pyxel.btnp(pyxel.KEY_Q):
pyxel.quit()

def check_reset(self) -> bool:
if pyxel.btnp(pyxel.KEY_R):
self.finished = True
self.next = "menu"
return True
return False

def check_anyone_alive(self) -> bool:
for p in self.player:
if p.alive:
return True
return False

def update_scroll_x(self, player):
# FIXME: We should get rid of this func
self.scroll_x = player.get_scroll_x()

def create_characters(self):
if self.player_choice == 0:
self.player = [Player1(0, 0)]
elif self.player_choice == 1:
self.player = [Player2(0, 0)]
elif self.player_choice == 2:
self.player = [Player1(0, 0), Player2(0, 10)]

def spawn(self, left_x, right_x):
left_x = math.ceil(left_x / 8)
right_x = math.floor(right_x / 8)
for x in range(left_x, right_x + 1):
for y in range(16):
if (x*8, y*8) in self.enemy_template:
mobclass = self.enemy_templates[(x*8, y*8)]
self.enemies.append(mobclass(x * 8, y * 8))

def update_template(self):
"Some update actions that should happen in (almost) every instance."
for p in self.player:
p.update()
for b in p.bullets:
b.update()
for e in self.enemies:
if b.x in range(e.x, e.x+9) and b.y in range(e.y, e.y+9):
e.alive = False
for e in self.enemies:
if e.alive:
if e.x in range(p.x, p.x+9) and e.y in range(p.y, p.y+9):
p.alive = False
if not self.check_anyone_alive():
self.lost = True
pyxel.playm(6)
self.startup()
return
for e in self.enemies:
e.update()
# NOTE: Only player 1 (Diddi, when multiplayer) will move the screen
# TODO: On multiplayer mode, allow both players to move the screen??
self.update_scroll_x(self.player[0])
player_x = self.player[0].x
if player_x > self.scroll_x + self.SCROLL_BORDER_X:
# Move the screen if needed
last_scroll_x = self.scroll_x
self.scroll_x = min(self.x - self.SCROLL_BORDER_X, 240 * 8)
self.spawn(last_scroll_x + 128, self.scroll_x + 127)

def draw_template(self):
"Some drawing actions that should happen in (almost) every instance."
pyxel.cls(0)
if self.check_anyone_alive():
pyxel.camera()
pyxel.bltm(0, 0, 1, self.scroll_x, self.draw_v, 128, 128, 0)
pyxel.camera(self.scroll_x, self.draw_v) # test: self.draw_v or 0?
for p in self.player:
p.draw()
for b in p.bullets:
b.draw()
for i in self.enemies:
i.draw()

@abstractmethod
def update(self):
pass

@abstractmethod
def draw(self):
pass
Loading

0 comments on commit 9bf445a

Please sign in to comment.