refactor to hatch
4
creeper_adventure/__about__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2023-present Waylon S. Walker <waylon@waylonwalker.com>
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
__version__ = '0.0.1'
|
||||
3
creeper_adventure/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# SPDX-FileCopyrightText: 2023-present Waylon S. Walker <waylon@waylonwalker.com>
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
9
creeper_adventure/__main__.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# SPDX-FileCopyrightText: 2023-present Waylon S. Walker <waylon@waylonwalker.com>
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
import sys
|
||||
|
||||
if __name__ == '__main__':
|
||||
from .cli import creeper_adventure
|
||||
|
||||
sys.exit(creeper_adventure())
|
||||
BIN
creeper_adventure/assets/bee/idle/1.png
Executable file
|
After Width: | Height: | Size: 630 B |
BIN
creeper_adventure/assets/chest.png
Normal file
|
After Width: | Height: | Size: 530 B |
BIN
creeper_adventure/assets/crafting-table.png
Normal file
|
After Width: | Height: | Size: 810 B |
BIN
creeper_adventure/assets/creeper/idle/1.png
Executable file
|
After Width: | Height: | Size: 769 B |
BIN
creeper_adventure/assets/creeper/idle/2.png
Executable file
|
After Width: | Height: | Size: 769 B |
BIN
creeper_adventure/assets/creeper/idle/3.png
Executable file
|
After Width: | Height: | Size: 769 B |
BIN
creeper_adventure/assets/creeper/idle/4.png
Executable file
|
After Width: | Height: | Size: 769 B |
BIN
creeper_adventure/assets/creeper/idle/5.png
Executable file
|
After Width: | Height: | Size: 776 B |
BIN
creeper_adventure/assets/grass.png
Normal file
|
After Width: | Height: | Size: 629 B |
BIN
creeper_adventure/assets/leaf.png
Executable file
|
After Width: | Height: | Size: 599 B |
BIN
creeper_adventure/assets/log.png
Normal file
|
After Width: | Height: | Size: 813 B |
BIN
creeper_adventure/assets/oak_trees/1.png
Executable file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
creeper_adventure/assets/oak_trees/2.png
Executable file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
creeper_adventure/assets/oak_trees/4.png
Executable file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
creeper_adventure/assets/oak_trees/5.png
Executable file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
creeper_adventure/assets/sounds/axe.mp3
Normal file
BIN
creeper_adventure/assets/sounds/short-axe.mp3
Normal file
BIN
creeper_adventure/assets/sounds/walking.mp3
Normal file
BIN
creeper_adventure/assets/spotlight.png
Executable file
|
After Width: | Height: | Size: 2 KiB |
BIN
creeper_adventure/assets/stev/idle/0.png
Normal file
|
After Width: | Height: | Size: 979 B |
BIN
creeper_adventure/assets/stev/idle/1.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
19
creeper_adventure/cli/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# SPDX-FileCopyrightText: 2023-present Waylon S. Walker <waylon@waylonwalker.com>
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
import click
|
||||
|
||||
from ..__about__ import __version__
|
||||
from ..creeper import main
|
||||
|
||||
|
||||
@click.group(
|
||||
context_settings={"help_option_names": ["-h", "--help"]},
|
||||
invoke_without_command=True,
|
||||
)
|
||||
@click.version_option(version=__version__, prog_name="creeper-adventure")
|
||||
@click.pass_context
|
||||
@click.option("--debug", is_flag=True, help="start with the debug menu open")
|
||||
def creeper_adventure(ctx: click.Context, debug):
|
||||
print(debug)
|
||||
main(debug)
|
||||
630
creeper_adventure/creeper.py
Executable file
|
|
@ -0,0 +1,630 @@
|
|||
import random
|
||||
from copy import copy
|
||||
from itertools import cycle, repeat
|
||||
from pathlib import Path
|
||||
|
||||
import pygame
|
||||
from more_itertools import flatten
|
||||
|
||||
from creeper_adventure.game import Game
|
||||
|
||||
ASSETS = Path(__file__).parent / "assets"
|
||||
|
||||
|
||||
class MouseSprite:
|
||||
def __init__(self, surf, hotbar):
|
||||
self.surf = surf
|
||||
self.hotbar = hotbar
|
||||
|
||||
@property
|
||||
def mouse_pos(self):
|
||||
return [i - 2 for i in pygame.mouse.get_pos()]
|
||||
|
||||
@property
|
||||
def rect(self):
|
||||
return pygame.Rect(self.mouse_pos, (4, 4))
|
||||
|
||||
def get_nearest_block_pos(self):
|
||||
return ([i - (i % 16) for i in pygame.mouse.get_pos()],)
|
||||
|
||||
def draw(self):
|
||||
if self.hotbar.selected.type is None:
|
||||
pygame.draw.rect(self.surf, (255, 0, 0), self.rect)
|
||||
else:
|
||||
self.img = pygame.image.load(ASSETS / f"{self.hotbar.selected.type}.png")
|
||||
self.surf.blit(
|
||||
pygame.transform.scale(self.img, (16, 16)),
|
||||
self.get_nearest_block_pos(),
|
||||
)
|
||||
|
||||
|
||||
class TreeSprite:
|
||||
def __init__(self, tree, x, y, scale, flip, surf):
|
||||
self.image = tree
|
||||
self.health = 100
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.scale = scale
|
||||
self.flip = flip
|
||||
self.surf = surf
|
||||
self.leafs = [Leaf(self, self.surf, (x + 25, y + 25)) for i in range(2)]
|
||||
self.shaking = 0
|
||||
|
||||
def shake(self):
|
||||
if self.shaking == 0:
|
||||
self.shaking = 10
|
||||
self.shaking_magnitude = random.randint(0, 10)
|
||||
self.leafs.extend(
|
||||
[
|
||||
Leaf(
|
||||
self,
|
||||
self.surf,
|
||||
(
|
||||
self.x + 25 + random.randint(-10, 10),
|
||||
self.y + 25 + random.randint(-10, 10),
|
||||
),
|
||||
lifespan=1,
|
||||
)
|
||||
for i in range(int(self.shaking_magnitude / 2))
|
||||
]
|
||||
)
|
||||
|
||||
@property
|
||||
def rotate(self):
|
||||
if self.shaking == 0:
|
||||
return 0
|
||||
self.shaking -= 1
|
||||
return random.randint(-self.shaking_magnitude, self.shaking_magnitude)
|
||||
|
||||
@property
|
||||
def rect(self):
|
||||
return pygame.Rect(
|
||||
self.x,
|
||||
self.y,
|
||||
self.scale,
|
||||
self.scale,
|
||||
)
|
||||
|
||||
def draw(self):
|
||||
if self.health > 0:
|
||||
self.surf.blit(
|
||||
pygame.transform.rotate(
|
||||
pygame.transform.flip(
|
||||
pygame.transform.scale(self.image, (self.scale, self.scale)),
|
||||
self.flip,
|
||||
False,
|
||||
),
|
||||
self.rotate,
|
||||
),
|
||||
(self.x, self.y),
|
||||
)
|
||||
for leaf in self.leafs:
|
||||
leaf.draw()
|
||||
|
||||
|
||||
class HotBar:
|
||||
def __init__(self, game: Game, scale=32, num=10, margin=None):
|
||||
if margin is None:
|
||||
margin = scale * 0.1
|
||||
self.scale = scale
|
||||
self.num = num
|
||||
self.margin = margin
|
||||
self.ui = pygame.Surface(
|
||||
(self.scale * self.num, self.scale), pygame.SRCALPHA, 32
|
||||
).convert_alpha()
|
||||
self.game = game
|
||||
self.items = [
|
||||
HotBarItem(
|
||||
game=self, surf=self.ui, pos=pos, scale=self.scale, margin=self.margin
|
||||
)
|
||||
for pos in range(num)
|
||||
]
|
||||
self.items[0].selected = True
|
||||
|
||||
@property
|
||||
def selected(self):
|
||||
return [bar for bar in self.items if bar.selected][0]
|
||||
|
||||
def next(self, step):
|
||||
cur_idx = self.items.index(self.selected)
|
||||
next_idx = cur_idx + step
|
||||
self.items[cur_idx].selected = False
|
||||
if next_idx >= len(self.items):
|
||||
self.items[0].selected = True
|
||||
elif next_idx < 0:
|
||||
self.items[-1].selected = True
|
||||
else:
|
||||
self.items[next_idx].selected = True
|
||||
|
||||
def draw(self):
|
||||
self.ui.fill((50, 50, 50))
|
||||
for i, item in enumerate(self.game.inventory):
|
||||
self.items[i].type = item
|
||||
for hot_bar_item in self.items:
|
||||
hot_bar_item.draw()
|
||||
|
||||
y = self.game.screen.get_size()[1] - self.scale - self.margin
|
||||
x = (self.game.screen.get_size()[0] - self.scale * self.num) / 2
|
||||
self.game.screen.blit(
|
||||
self.ui,
|
||||
(x, y),
|
||||
)
|
||||
|
||||
|
||||
class HotBarItem:
|
||||
def __init__(self, game: Game, surf, pos=0, scale=24, margin=4):
|
||||
self.ui = surf
|
||||
self.game = game
|
||||
self.scale = scale
|
||||
self.margin = margin
|
||||
self.surf = pygame.Surface(
|
||||
(self.scale - self.margin * 2, self.scale - self.margin * 2)
|
||||
).convert_alpha()
|
||||
self.pos = pos
|
||||
self.selected = False
|
||||
self.surf.fill((0, 0, 0))
|
||||
self.type = None
|
||||
|
||||
def draw(self):
|
||||
self.surf.fill((0, 0, 0, 60))
|
||||
if self.selected:
|
||||
self.surf.fill((185, 185, 205, 60))
|
||||
|
||||
if self.type:
|
||||
self.img = pygame.image.load(ASSETS / f"{self.type}.png")
|
||||
self.ui.blit(
|
||||
pygame.transform.scale(
|
||||
self.img,
|
||||
(self.scale - self.margin * 2, self.scale - self.margin * 2),
|
||||
),
|
||||
(self.pos * self.scale + self.margin, self.margin),
|
||||
)
|
||||
font = pygame.font.SysFont(None, self.scale)
|
||||
qty = str(self.game.game.inventory[self.type])
|
||||
img = font.render(qty, True, (255, 255, 255))
|
||||
self.ui.blit(
|
||||
pygame.transform.scale(img, (self.scale * 0.6, self.scale * 0.6)),
|
||||
(self.pos * self.scale + self.margin, self.margin),
|
||||
)
|
||||
|
||||
self.ui.blit(
|
||||
self.surf.convert_alpha(),
|
||||
(self.pos * self.scale + self.margin, self.margin),
|
||||
)
|
||||
|
||||
|
||||
class Menu:
|
||||
def __init__(
|
||||
self,
|
||||
game: Game,
|
||||
title: str = "menu",
|
||||
scale: int = 32,
|
||||
margin: int = 16,
|
||||
alpha=225,
|
||||
):
|
||||
self.game = game
|
||||
self.is_open = False
|
||||
self.title = title
|
||||
self.scale = scale
|
||||
self.margin = margin
|
||||
self.alpha = alpha
|
||||
|
||||
def draw(self):
|
||||
if self.is_open:
|
||||
self.surf = pygame.Surface(self.game.screen.get_size()).convert_alpha()
|
||||
self.surf.fill((0, 0, 0, self.alpha))
|
||||
font = pygame.font.SysFont(None, self.scale)
|
||||
img = font.render(self.title, True, (255, 255, 255))
|
||||
self.surf.blit(
|
||||
img,
|
||||
(10, 10)
|
||||
# (100 * self.scale + self.margin, self.margin),
|
||||
)
|
||||
self._draw()
|
||||
|
||||
self.game.screen.blit(self.surf, (0, 0))
|
||||
|
||||
def _draw(self):
|
||||
...
|
||||
|
||||
|
||||
class DebugMenu(Menu):
|
||||
def __init__(self, game):
|
||||
super().__init__(title="Debug Menu", game=game, alpha=0)
|
||||
self.font = pygame.font.SysFont(None, 20)
|
||||
|
||||
def _draw(self):
|
||||
self.surf.blit(
|
||||
self.font.render(
|
||||
f"(x, y): ({self.game.x}, {self.game.y})", True, (255, 255, 255)
|
||||
),
|
||||
(10, 35),
|
||||
)
|
||||
self.surf.blit(
|
||||
self.font.render(
|
||||
f"mouse_pos: {pygame.mouse.get_pos()}", True, (255, 255, 255)
|
||||
),
|
||||
(10, 50),
|
||||
)
|
||||
self.surf.blit(
|
||||
self.font.render(
|
||||
f"nearest block pos: {self.game.mouse_box.get_nearest_block_pos()}",
|
||||
True,
|
||||
(255, 255, 255),
|
||||
),
|
||||
(10, 65),
|
||||
)
|
||||
self.surf.blit(
|
||||
self.font.render(
|
||||
f"walking sound: {self.game.walking_sound_is_playing}",
|
||||
True,
|
||||
(255, 255, 255),
|
||||
),
|
||||
(10, 80),
|
||||
)
|
||||
|
||||
|
||||
class LightSource:
|
||||
def __init__(self, game: Game, surf, img, center):
|
||||
self.surf = surf
|
||||
self.game = game
|
||||
self.img = img
|
||||
self.center = center
|
||||
self.sx, self.sy = center
|
||||
self.spot = pygame.image.load(ASSETS / "spotlight.png")
|
||||
|
||||
|
||||
class Leaf:
|
||||
def __init__(self, game: Game, surf, center, lifespan=None):
|
||||
self.surf = surf
|
||||
self.game = game
|
||||
self.center = center
|
||||
self.sx, self.sy = center
|
||||
self.img = pygame.transform.scale(
|
||||
pygame.image.load(ASSETS / "leaf.png"), (4, 4)
|
||||
).convert_alpha()
|
||||
self.lifespan = lifespan
|
||||
self.r = random.randint(0, 360)
|
||||
self.x, self.y = [int(i) + random.randint(-8, 8) for i in self.center]
|
||||
self.restart()
|
||||
|
||||
def restart(self):
|
||||
if self.lifespan is not None:
|
||||
self.lifespan -= 1
|
||||
if self.lifespan is None or self.lifespan > 0:
|
||||
self.r = random.randint(0, 360)
|
||||
self.x, self.y = [int(i) + random.randint(-8, 8) for i in self.center]
|
||||
|
||||
def draw(self):
|
||||
self.surf.blit(
|
||||
pygame.transform.rotate(self.img, self.r), (int(self.x), int(self.y))
|
||||
)
|
||||
|
||||
if self.y < self.sy + 40:
|
||||
self.y += random.randint(0, 5) / 4
|
||||
self.x += random.randint(-15, 5) / 10
|
||||
self.r += random.randint(-10, 10)
|
||||
elif self.y < self.sy + 45:
|
||||
self.y += random.randint(-2, 5) / 10
|
||||
self.x += random.randint(-18, 2) / 10
|
||||
self.r += random.randint(-10, 25)
|
||||
else:
|
||||
self.restart()
|
||||
if self.x > self.sx + 100:
|
||||
self.restart()
|
||||
|
||||
|
||||
class Bee:
|
||||
def __init__(self):
|
||||
self.bee = pygame.image.load(ASSETS / "bee/idle/1.png")
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
|
||||
def draw(self, screen, x, y):
|
||||
self.x += random.randint(-2, 2)
|
||||
self.y += random.randint(-2, 2)
|
||||
screen.blit(
|
||||
self.bee,
|
||||
(
|
||||
x + self.x - self.bee.get_size()[0] / 2,
|
||||
y + self.y - self.bee.get_size()[1] / 2,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class Creeper(Game):
|
||||
def __init__(self, debug=False):
|
||||
super().__init__()
|
||||
self.inventory = {}
|
||||
self.day_len = 1000 * 60
|
||||
self.background = pygame.Surface(self.screen.get_size())
|
||||
self.foreground = pygame.Surface(self.screen.get_size())
|
||||
self.build = pygame.Surface(self.screen.get_size())
|
||||
self.darkness = pygame.Surface(self.screen.get_size()).convert_alpha()
|
||||
self.axe_sound = pygame.mixer.Sound(ASSETS / "sounds/axe.mp3")
|
||||
self.walking_sound = pygame.mixer.Sound(ASSETS / "sounds/walking.mp3")
|
||||
self.walking_sound_is_playing = False
|
||||
|
||||
self.background.fill((0, 255, 247))
|
||||
self.x, self.y = [i / 2 for i in self.screen.get_size()]
|
||||
self.spot = pygame.image.load(ASSETS / "spotlight.png")
|
||||
self.light_power = 1.1
|
||||
self.leaf = pygame.transform.scale(
|
||||
pygame.image.load(ASSETS / "leaf.png"), (4, 4)
|
||||
).convert_alpha()
|
||||
self.creepers = cycle(
|
||||
flatten(
|
||||
[
|
||||
repeat(pygame.image.load(img), 5)
|
||||
for img in Path(ASSETS / "stev/idle/").glob("*.png")
|
||||
]
|
||||
)
|
||||
)
|
||||
self.tree_imgs = [
|
||||
pygame.image.load(img) for img in Path(ASSETS / "oak_trees/").glob("*.png")
|
||||
]
|
||||
# self.creeper = pygame.image.load(ASSETS/"creeper/idle/1.png")
|
||||
self.creeper = next(self.creepers)
|
||||
self.bee = Bee()
|
||||
x = 0
|
||||
self.hotbar = HotBar(game=self)
|
||||
self.leafs = []
|
||||
self.trees = []
|
||||
|
||||
x_range = [
|
||||
self.screen.get_size()[0] * 0.1,
|
||||
self.screen.get_size()[0] * 0.9,
|
||||
]
|
||||
y_range = [
|
||||
self.screen.get_size()[1] * 0.35,
|
||||
self.screen.get_size()[1] * 0.5,
|
||||
]
|
||||
for i in range(10):
|
||||
x = random.randint(*x_range)
|
||||
y = random.randint(*y_range)
|
||||
|
||||
scale = random.randint(42, 86)
|
||||
self.trees.append(
|
||||
TreeSprite(
|
||||
tree=random.choice(self.tree_imgs),
|
||||
x=x,
|
||||
y=y,
|
||||
scale=scale,
|
||||
flip=random.randint(0, 1),
|
||||
surf=self.background,
|
||||
)
|
||||
)
|
||||
|
||||
self.mouse_box = MouseSprite(self.screen, hotbar=self.hotbar)
|
||||
self.joysticks = {}
|
||||
self.hotbar_back_debounce = 1
|
||||
self.hotbar_forward_debounce = 1
|
||||
self.inventory_open_debounce = 1
|
||||
self.debug_open_debounce = 1
|
||||
self.main_open_debounce = 1
|
||||
self.inventory_menu = Menu(self, title="inventory")
|
||||
self.debug_menu = DebugMenu(self)
|
||||
self.debug_menu.is_open = debug
|
||||
self.main_menu = Menu(self, title="main menu")
|
||||
|
||||
def attack(self):
|
||||
|
||||
collisions = self.mouse_box.rect.collidedictall(
|
||||
{tree: tree.rect for tree in self.trees}
|
||||
)
|
||||
if not collisions:
|
||||
return False
|
||||
for collision in collisions:
|
||||
tree = collision[0]
|
||||
tree.health -= 10
|
||||
tree.hit = True
|
||||
tree.shake()
|
||||
self.axe_sound.play()
|
||||
return True
|
||||
|
||||
def place_block(self):
|
||||
if self.hotbar.selected.type is None:
|
||||
return False
|
||||
|
||||
def process_deaths(self):
|
||||
for i, tree in enumerate(copy(self.trees)):
|
||||
if tree.health <= 0:
|
||||
self.inventory["log"] = self.inventory.get("log", 0) + 10
|
||||
try:
|
||||
del self.trees[i]
|
||||
except IndexError:
|
||||
# get this one on the next pass
|
||||
# killing two items in the same frame will error
|
||||
...
|
||||
|
||||
def normal_keys(self):
|
||||
keys = self.keys
|
||||
if keys[pygame.K_a]:
|
||||
self.x -= 10
|
||||
if keys[pygame.K_d]:
|
||||
self.x += 10
|
||||
if keys[pygame.K_w]:
|
||||
self.y -= 10
|
||||
if keys[pygame.K_d]:
|
||||
self.y += 10
|
||||
if keys[pygame.K_k]:
|
||||
self.hotbar.next(1)
|
||||
if keys[pygame.K_j]:
|
||||
self.hotbar.next(-1)
|
||||
|
||||
for event in self.events:
|
||||
if event.type == pygame.MOUSEWHEEL:
|
||||
self.hotbar.next(event.y)
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if pygame.mouse.get_pressed()[0]:
|
||||
did_attack = self.attack()
|
||||
if pygame.mouse.get_pressed()[2]:
|
||||
did_place = self.place_block()
|
||||
|
||||
if event.type == pygame.JOYDEVICEADDED:
|
||||
# This event will be generated when the program starts for every
|
||||
# joystick, filling up the list without needing to create them manually.
|
||||
joy = pygame.joystick.Joystick(event.device_index)
|
||||
self.joysticks[joy.get_instance_id()] = joy
|
||||
if event.type == pygame.JOYDEVICEREMOVED:
|
||||
del self.joysticks[event.instance_id]
|
||||
|
||||
for joystick in self.joysticks.values():
|
||||
|
||||
if joystick.get_button(4) and self.hotbar_back_debounce:
|
||||
self.hotbar.next(-1)
|
||||
self.hotbar_back_debounce = 0
|
||||
elif not joystick.get_button(4):
|
||||
self.hotbar_back_debounce = 1
|
||||
|
||||
if joystick.get_button(5) and self.hotbar_forward_debounce:
|
||||
self.hotbar.next(1)
|
||||
self.hotbar_forward_debounce = 0
|
||||
elif not joystick.get_button(5):
|
||||
self.hotbar_forward_debounce = 1
|
||||
|
||||
if (
|
||||
keys[pygame.K_e] or joystick.get_button(2)
|
||||
) and self.inventory_open_debounce:
|
||||
self.inventory_menu.is_open = not self.inventory_menu.is_open
|
||||
self.inventory_open_debounce = 0
|
||||
elif not (keys[pygame.K_e] or joystick.get_button(2)):
|
||||
self.inventory_open_debounce = 1
|
||||
|
||||
if (
|
||||
keys[pygame.K_ESCAPE] or joystick.get_button(9)
|
||||
) and self.main_open_debounce:
|
||||
self.main_menu.is_open = not self.main_menu.is_open
|
||||
self.main_open_debounce = 0
|
||||
elif not (keys[pygame.K_ESCAPE] or joystick.get_button(9)):
|
||||
self.main_open_debounce = 1
|
||||
|
||||
if keys[pygame.K_F3] and self.debug_open_debounce:
|
||||
self.debug_menu.is_open = not self.debug_menu.is_open
|
||||
self.debug_open_debounce = 0
|
||||
elif not keys[pygame.K_F3]:
|
||||
self.debug_open_debounce = 1
|
||||
|
||||
hats = joystick.get_numhats()
|
||||
for i in range(hats):
|
||||
hat = joystick.get_hat(i)
|
||||
if hat[0] == 1:
|
||||
self.x += 10
|
||||
if hat[0] == -1:
|
||||
self.x -= 10
|
||||
if hat[1] == -1:
|
||||
self.y += 10
|
||||
if hat[1] == 1:
|
||||
self.y -= 10
|
||||
|
||||
if abs(joystick.get_axis(0)) > 0.2:
|
||||
self.x += joystick.get_axis(0) * 10
|
||||
if abs(joystick.get_axis(1)) > 0.2:
|
||||
self.y += joystick.get_axis(1) * 10
|
||||
|
||||
def inventory_keys(self):
|
||||
keys = self.keys
|
||||
for joystick in self.joysticks.values():
|
||||
if (
|
||||
keys[pygame.K_e] or joystick.get_button(2)
|
||||
) and self.inventory_open_debounce:
|
||||
self.inventory_menu.is_open = not self.inventory_menu.is_open
|
||||
self.inventory_open_debounce = 0
|
||||
elif not (keys[pygame.K_e] or joystick.get_button(2)):
|
||||
self.inventory_open_debounce = 1
|
||||
|
||||
def main_keys(self):
|
||||
keys = self.keys
|
||||
for joystick in self.joysticks.values():
|
||||
if (
|
||||
keys[pygame.K_ESCAPE] or joystick.get_button(9)
|
||||
) and self.main_open_debounce:
|
||||
self.main_menu.is_open = not self.main_menu.is_open
|
||||
self.main_open_debounce = 0
|
||||
elif not (keys[pygame.K_ESCAPE] or joystick.get_button(9)):
|
||||
self.main_open_debounce = 1
|
||||
|
||||
def make_sound(self):
|
||||
if not hasattr(self, "last_x"):
|
||||
self.last_x = self.x
|
||||
if not hasattr(self, "last_y"):
|
||||
self.last_y = self.y
|
||||
if (
|
||||
self.last_x == self.x and self.last_y == self.y
|
||||
) and self.walking_sound_is_playing:
|
||||
self.walking_sound.stop()
|
||||
self.walking_sound_is_playing = False
|
||||
|
||||
if (
|
||||
self.last_x != self.x or self.last_y != self.y
|
||||
) and not self.walking_sound_is_playing:
|
||||
self.walking_sound.play()
|
||||
self.walking_sound_is_playing = True
|
||||
if self.last_x != self.x or self.last_y != self.y:
|
||||
|
||||
self.creeper = next(self.creepers)
|
||||
self.last_x = self.x
|
||||
self.last_y = self.y
|
||||
|
||||
def game(self):
|
||||
self.screen.blit(self.background, (0, 0))
|
||||
self.background.fill((0, 255, 247))
|
||||
self.process_deaths()
|
||||
for tree in self.trees:
|
||||
tree.draw()
|
||||
|
||||
self.screen.blit(
|
||||
self.creeper,
|
||||
(
|
||||
self.x - self.creeper.get_size()[0] / 2,
|
||||
self.y - self.creeper.get_size()[1] / 2,
|
||||
),
|
||||
)
|
||||
self.bee.draw(self.screen, self.x, self.y)
|
||||
for leaf in self.leafs:
|
||||
leaf.draw()
|
||||
|
||||
light_level = pygame.time.get_ticks() % self.day_len
|
||||
light_level = abs(light_level * (255 * 2 / self.day_len) - 255)
|
||||
|
||||
self.darkness.fill((light_level, light_level, light_level))
|
||||
if self.light_power < 500:
|
||||
self.light_power = min(self.light_power**1.1, 500)
|
||||
self.darkness.blit(
|
||||
pygame.transform.smoothscale(
|
||||
self.spot, [self.light_power, self.light_power]
|
||||
),
|
||||
(self.x - self.light_power / 2, self.y - self.light_power / 2),
|
||||
)
|
||||
self.screen.blit(
|
||||
self.darkness,
|
||||
(0, 0),
|
||||
special_flags=pygame.BLEND_RGBA_MULT,
|
||||
)
|
||||
|
||||
self.hotbar.draw()
|
||||
self.debug_menu.draw()
|
||||
self.inventory_menu.draw()
|
||||
self.main_menu.draw()
|
||||
|
||||
self.mouse_box = MouseSprite(self.screen, hotbar=self.hotbar)
|
||||
|
||||
self.mouse_box.draw()
|
||||
|
||||
self.make_sound()
|
||||
|
||||
if self.inventory_menu.is_open:
|
||||
self.inventory_keys()
|
||||
elif self.main_menu.is_open:
|
||||
self.main_keys()
|
||||
else:
|
||||
self.normal_keys()
|
||||
|
||||
|
||||
def main(debug=False):
|
||||
creeper = Creeper(debug=debug)
|
||||
creeper.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
46
creeper_adventure/game.py
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
import pygame
|
||||
|
||||
|
||||
class Game:
|
||||
def __init__(self):
|
||||
pygame.init()
|
||||
pygame.mixer.init()
|
||||
pygame.display.set_caption(__file__)
|
||||
|
||||
self.screen_size = (854, 480)
|
||||
self.screen_size = (1280, 800)
|
||||
self.screen_size = (1920, 1080)
|
||||
self.screen = pygame.display.set_mode(self.screen_size)
|
||||
self.clock = pygame.time.Clock()
|
||||
|
||||
self.running = True
|
||||
self.surfs = []
|
||||
|
||||
def should_quit(self):
|
||||
for event in self.events:
|
||||
if event.type == pygame.QUIT:
|
||||
self.running = False
|
||||
|
||||
def game(self):
|
||||
...
|
||||
|
||||
def reset_screen(self):
|
||||
self.screen.fill((0, 0, 0))
|
||||
|
||||
def run(self):
|
||||
while self.running:
|
||||
self.events = pygame.event.get()
|
||||
self.should_quit()
|
||||
self.reset_screen()
|
||||
self.keys = pygame.key.get_pressed()
|
||||
self.game()
|
||||
for surf in self.surfs:
|
||||
pygame.blit(surf)
|
||||
pygame.display.update()
|
||||
self.clock.tick(30)
|
||||
pygame.quit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
game = Game()
|
||||
game.run()
|
||||
149
creeper_adventure/joytest.py
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
import pygame
|
||||
|
||||
pygame.init()
|
||||
# This is a simple class that will help us print to the screen.
|
||||
# It has nothing to do with the joysticks, just outputting the
|
||||
# information.
|
||||
class TextPrint:
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
self.font = pygame.font.Font(None, 25)
|
||||
|
||||
def tprint(self, screen, text):
|
||||
text_bitmap = self.font.render(text, True, (0, 0, 0))
|
||||
screen.blit(text_bitmap, (self.x, self.y))
|
||||
self.y += self.line_height
|
||||
|
||||
def reset(self):
|
||||
self.x = 10
|
||||
self.y = 10
|
||||
self.line_height = 15
|
||||
|
||||
def indent(self):
|
||||
self.x += 10
|
||||
|
||||
def unindent(self):
|
||||
self.x -= 10
|
||||
|
||||
|
||||
def main():
|
||||
# Set the width and height of the screen (width, height), and name the window.
|
||||
screen = pygame.display.set_mode((500, 700))
|
||||
pygame.display.set_caption("Joystick example")
|
||||
|
||||
# Used to manage how fast the screen updates.
|
||||
clock = pygame.time.Clock()
|
||||
|
||||
# Get ready to print.
|
||||
text_print = TextPrint()
|
||||
|
||||
# This dict can be left as-is, since pygame will generate a
|
||||
# pygame.JOYDEVICEADDED event for every joystick connected
|
||||
# at the start of the program.
|
||||
joysticks = {}
|
||||
|
||||
done = False
|
||||
while not done:
|
||||
# Event processing step.
|
||||
# Possible joystick events: JOYAXISMOTION, JOYBALLMOTION, JOYBUTTONDOWN,
|
||||
# JOYBUTTONUP, JOYHATMOTION, JOYDEVICEADDED, JOYDEVICEREMOVED
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
done = True # Flag that we are done so we exit this loop.
|
||||
|
||||
if event.type == pygame.JOYBUTTONDOWN:
|
||||
print("Joystick button pressed.")
|
||||
if event.button == 0:
|
||||
joystick = joysticks[event.instance_id]
|
||||
if joystick.rumble(0, 0.7, 500):
|
||||
print(f"Rumble effect played on joystick {event.instance_id}")
|
||||
|
||||
if event.type == pygame.JOYBUTTONUP:
|
||||
print("Joystick button released.")
|
||||
|
||||
# Handle hotplugging
|
||||
if event.type == pygame.JOYDEVICEADDED:
|
||||
# This event will be generated when the program starts for every
|
||||
# joystick, filling up the list without needing to create them manually.
|
||||
joy = pygame.joystick.Joystick(event.device_index)
|
||||
joysticks[joy.get_instance_id()] = joy
|
||||
print(f"Joystick {joy.get_instance_id()} connencted")
|
||||
|
||||
if event.type == pygame.JOYDEVICEREMOVED:
|
||||
del joysticks[event.instance_id]
|
||||
print(f"Joystick {event.instance_id} disconnected")
|
||||
|
||||
# Drawing step
|
||||
# First, clear the screen to white. Don't put other drawing commands
|
||||
# above this, or they will be erased with this command.
|
||||
screen.fill((255, 255, 255))
|
||||
text_print.reset()
|
||||
|
||||
# Get count of joysticks.
|
||||
joystick_count = pygame.joystick.get_count()
|
||||
|
||||
text_print.tprint(screen, f"Number of joysticks: {joystick_count}")
|
||||
text_print.indent()
|
||||
|
||||
# For each joystick:
|
||||
for joystick in joysticks.values():
|
||||
jid = joystick.get_instance_id()
|
||||
|
||||
text_print.tprint(screen, f"Joystick {jid}")
|
||||
text_print.indent()
|
||||
|
||||
# Get the name from the OS for the controller/joystick.
|
||||
name = joystick.get_name()
|
||||
text_print.tprint(screen, f"Joystick name: {name}")
|
||||
|
||||
guid = joystick.get_guid()
|
||||
text_print.tprint(screen, f"GUID: {guid}")
|
||||
|
||||
power_level = joystick.get_power_level()
|
||||
text_print.tprint(screen, f"Joystick's power level: {power_level}")
|
||||
|
||||
# Usually axis run in pairs, up/down for one, and left/right for
|
||||
# the other. Triggers count as axes.
|
||||
axes = joystick.get_numaxes()
|
||||
text_print.tprint(screen, f"Number of axes: {axes}")
|
||||
text_print.indent()
|
||||
|
||||
for i in range(axes):
|
||||
axis = joystick.get_axis(i)
|
||||
text_print.tprint(screen, f"Axis {i} value: {axis:>6.3f}")
|
||||
text_print.unindent()
|
||||
|
||||
buttons = joystick.get_numbuttons()
|
||||
text_print.tprint(screen, f"Number of buttons: {buttons}")
|
||||
text_print.indent()
|
||||
|
||||
for i in range(buttons):
|
||||
button = joystick.get_button(i)
|
||||
text_print.tprint(screen, f"Button {i:>2} value: {button}")
|
||||
text_print.unindent()
|
||||
|
||||
hats = joystick.get_numhats()
|
||||
text_print.tprint(screen, f"Number of hats: {hats}")
|
||||
text_print.indent()
|
||||
|
||||
# Hat position. All or nothing for direction, not a float like
|
||||
# get_axis(). Position is a tuple of int values (x, y).
|
||||
for i in range(hats):
|
||||
hat = joystick.get_hat(i)
|
||||
text_print.tprint(screen, f"Hat {i} value: {str(hat)}")
|
||||
text_print.unindent()
|
||||
|
||||
text_print.unindent()
|
||||
|
||||
# Go ahead and update the screen with what we've drawn.
|
||||
pygame.display.flip()
|
||||
|
||||
# Limit to 30 frames per second.
|
||||
clock.tick(30)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# If you forget this line, the program will 'hang'
|
||||
# on exit if running from IDLE.
|
||||
pygame.quit()
|
||||