Загрузка данных
import pygame, sys, random, math
pygame.init()
pygame.mixer.init()
V_W, V_H = 800, 450
info = pygame.display.Info()
REAL_W, REAL_H = (info.current_w, info.current_h) if info.current_w > 0 else (1280, 720)
screen = pygame.display.set_mode((REAL_W, REAL_H), pygame.FULLSCREEN | pygame.SCALED)
virtual_surface = pygame.Surface((V_W, V_H))
clock = pygame.time.Clock()
def create_sound(freqs, duration):
buf = bytearray(int(127 + 127 * math.sin(2 * math.pi * freqs[int((i / int(22050 * (duration / 1000.0))) * len(freqs))] * (i / 22050))) for i in range(int(22050 * (duration / 1000.0))))
try: return pygame.mixer.Sound(buffer=buf)
except: return None
snd_jump, snd_coin, snd_strike = create_sound([150, 300], 150), create_sound([600, 900], 100), create_sound([100, 50], 250)
class Player:
def __init__(self, x, y):
self.rect = pygame.Rect(x, y, 32, 40)
self.vx = self.vy = 0
self.on_ground = self.facing_right = True
self.strike_cooldown = self.strike_active = 0
def update(self, platforms):
if self.strike_cooldown > 0: self.strike_cooldown -= 1
if self.strike_active > 0:
self.strike_active -= 1; self.vy = 0; self.vx = 12 if self.facing_right else -12
else:
self.vy += 0.6
if self.vy > 10: self.vy = 10
self.rect.x += self.vx
for p in platforms:
if self.rect.colliderect(p.rect):
if self.vx > 0: self.rect.right = p.rect.left
elif self.vx < 0: self.rect.left = p.rect.right
self.rect.y += self.vy; self.on_ground = False
for p in platforms:
if self.rect.colliderect(p.rect):
if self.vy > 0: self.rect.bottom = p.rect.top; self.vy = 0; self.on_ground = True
elif self.vy < 0: self.rect.top = p.rect.bottom; self.vy = 0
self.rect.left = max(0, min(self.rect.left, 3000 - self.rect.width))
def draw(self, surf, cam_x):
rx = self.rect.x - cam_x
pygame.draw.ellipse(surf, (139,69,19), (rx, self.rect.y, 32, 40))
ex = rx + 24 if self.facing_right else rx + 8
pygame.draw.circle(surf, (0,0,0), (ex, self.rect.y + 12), 3)
if self.strike_active > 0:
for _ in range(3): pygame.draw.circle(surf, (147,112,219), (rx+16+random.randint(-10,10), self.rect.y+20+random.randint(-10,10)), random.randint(3,6))
def trigger_strike(self, particles):
if self.strike_cooldown == 0:
self.strike_cooldown, self.strike_active = 90, 15
if snd_strike: snd_strike.play()
d = 1 if self.facing_right else -1
for _ in range(15): particles.append(Particle(self.rect.x+(32 if self.facing_right else 0), self.rect.centery+random.randint(-10,10), random.uniform(3,7)*d, random.uniform(-2,2), (147,112,219), random.randint(10,20)))
class Platform:
def __init__(self, x, y, w, h): self.rect = pygame.Rect(x, y, w, h)
def draw(self, surf, cam_x):
pygame.draw.rect(surf, (34,139,34), (self.rect.x - cam_x, self.rect.y, self.rect.width, 10))
pygame.draw.rect(surf, (139,69,19), (self.rect.x - cam_x, self.rect.y + 10, self.rect.width, self.rect.height - 10))
class Coin:
def __init__(self, x, y): self.rect, self.collected = pygame.Rect(x, y, 20, 20), False
def draw(self, surf, cam_x):
if not self.collected: pygame.draw.circle(surf, (255,215,0), (self.rect.centerx - cam_x, self.rect.centery), 10)
class Ball:
def __init__(self, x, y): self.rect, self.vx, self.vy = pygame.Rect(x, y, 32, 32), 0, 0
def update(self, platforms, player, particles):
self.vy += 0.5
if self.rect.colliderect(player.rect):
if player.strike_active > 0:
self.vx = 16 if player.facing_right else -16; self.vy = -12
for _ in range(20): particles.append(Particle(self.rect.centerx, self.rect.centery, random.uniform(-6,6), random.uniform(-8,2), (147,112,219), random.randint(15,30)))
else:
self.vx = 4 if player.rect.centerx < self.rect.centerx else -4; self.vy = -4
self.vx *= 0.95; self.rect.x += int(self.vx)
for p in platforms:
if self.rect.colliderect(p.rect): self.vx *= -0.6
self.rect.y += int(self.vy)
for p in platforms:
if self.rect.colliderect(p.rect):
if self.vy > 0: self.rect.bottom = p.rect.top; self.vy = int(self.vy * -0.5)
else: self.rect.top = p.rect.bottom; self.vy = 0
self.rect.left = max(0, min(self.rect.left, 3000 - 32))
def draw(self, surf, cam_x):
rx = self.rect.x - cam_x
pygame.draw.circle(surf, (255,255,255), (rx + 16, self.rect.y + 16), 16)
pygame.draw.circle(surf, (0,0,0), (rx + 16, self.rect.y + 16), 16, 2)
class Particle:
def __init__(self, x, y, vx, vy, color, life): self.x, self.y, self.vx, self.vy, self.color, self.life = x, y, vx, vy, color, life
def update(self): self.x += self.vx; self.y += self.vy; self.life -= 1
def draw(self, surf, cam_x):
if self.life > 0: pygame.draw.circle(surf, self.color, (int(self.x - cam_x), int(self.y)), int(max(1, self.life / 4)))
class TouchButton:
def __init__(self, x, y, w, h, label, color): self.rect, self.label, self.color, self.is_pressed = pygame.Rect(x, y, w, h), label, color, False
def draw(self, surf):
btn_surf = pygame.Surface((self.rect.width, self.rect.height), pygame.SRCALPHA)
pygame.draw.rect(btn_surf, self.color + (180 if self.is_pressed else 100,), (0, 0, self.rect.width, self.rect.height), border_radius=12)
surf.blit(btn_surf, (self.rect.x, self.rect.y))
t = pygame.font.SysFont(None, 24).render(self.label, True, (255,255,255))
surf.blit(t, t.get_rect(center=self.rect.center))
def load_level():
global player, platforms, coins, ball, particles, score
player, score, particles = Player(100, 200), 0, []
platforms = [Platform(0,V_H-40,1200,40), Platform(1300,V_H-40,1000,40), Platform(2400,V_H-40,600,40), Platform(300,V_H-120,200,20), Platform(600,V_H-180,200,20)]
coins = [Coin(350,V_H-160), Coin(400,V_H-160), Coin(650,V_H-220)]
ball = Ball(450, V_H-100)
load_level()
btn_l, btn_r = TouchButton(20,V_H-90,70,70,"<-",(40,40,40)), TouchButton(110,V_H-90,70,70,"->",(40,40,40))
btn_j, btn_s = TouchButton(V_W-90,V_H-90,70,70,"JUMP",(0,100,250)), TouchButton(V_W-180,V_H-90,70,70,"HIT",(147,112,219))
buttons = [btn_l, btn_r, btn_j, btn_s]
cam_x = 0
while True:
for b in buttons: b.is_pressed = False
touch_pos = []
if pygame.mouse.get_pressed()[0]:
mx, my = pygame.mouse.get_pos()
touch_pos.append((int(mx * (V_W / REAL_W)), int(my * (V_H / REAL_H))))
for event in pygame.event.get():
if event.type == pygame.QUIT: pygame.quit(); sys.exit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_c: player.trigger_strike(particles)
for tx, ty in touch_pos:
for b in buttons:
if b.rect.collidepoint(tx, ty): b.is_pressed = True
if btn_l.is_pressed: player.vx = -5; player.facing_right = False
elif btn_r.is_pressed: player.vx = 5; player.facing_right = True
else: player.vx = 0
if btn_j.is_pressed and player.on_ground:
player.vy = -12
if snd_jump: snd_jump.play()
if btn_s.is_pressed: player.trigger_strike(particles)
player.update(platforms)
ball.update(platforms, player, particles)
for c in coins:
if not c.collected and player.rect.colliderect(c.rect):
c.collected = True; score += 1
if snd_coin: snd_coin.play()
for p in particles[:]:
p.update()
if p.life <= 0: particles.remove(p)
cam_x += (player.rect.x - cam_x - V_W // 2) * 0.1
cam_x = max(0, min(cam_x, 3000 - V_W))
if player.rect.y > V_H + 50: load_level()
virtual_surface.fill((135,206,235))
for p in platforms: p.draw(virtual_surface, cam_x)
for c in coins: c.draw(virtual_surface, cam_x)
ball.draw(virtual_surface, cam_x)
for p in particles: p.draw(virtual_surface, cam_x)
player.draw(virtual_surface, cam_x)
for b in buttons: b.draw(virtual_surface)
txt = pygame.font.SysFont(None, 24).render("READY" if player.strike_cooldown==0 else f"CD: {round(player.strike_cooldown/60,1)}s", True, (147,112,219))
virtual_surface.blit(txt, (V_W - 100, 15))
s_txt = pygame.font.SysFont(None, 24).render(f"Coins: {score}", True, (255,215,0))
virtual_surface.blit(s_txt, (20, 15))
screen.blit(pygame.transform.scale(virtual_surface, (REAL_W, REAL_H)), (0, 0))
pygame.display.flip()
clock.tick(60)