changeset 150:4f46717390aa

Introduce items, implement ECL instruction 83
author Thibaut Girka <thib@sitedethib.com>
date Tue, 04 Oct 2011 23:09:41 +0200
parents 3673d55a8448
children 5cf927cbd9c5
files pytouhou/game/game.py pytouhou/game/games.py pytouhou/game/item.py pytouhou/game/itemtype.py pytouhou/game/sprite.py pytouhou/opengl/gamerenderer.pyx pytouhou/vm/eclrunner.py
diffstat 7 files changed, 102 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/game/game.py
+++ b/pytouhou/game/game.py
@@ -19,19 +19,22 @@ from pytouhou.vm.eclrunner import ECLMai
 
 from pytouhou.game.player import Player
 from pytouhou.game.enemy import Enemy
+from pytouhou.game.item import Item
 
 
 class GameState(object):
-    __slots__ = ('resource_loader', 'bullets', 'players', 'rank', 'difficulty', 'frame',
-                 'stage', 'boss', 'prng', 'bullet_types', 'characters', 'nb_bullets_max')
+    __slots__ = ('resource_loader', 'bullets', 'items', 'players', 'rank', 'difficulty', 'frame',
+                 'stage', 'boss', 'prng', 'bullet_types', 'item_types', 'characters', 'nb_bullets_max')
     def __init__(self, resource_loader, players, stage, rank, difficulty,
-                 bullet_types, characters, nb_bullets_max):
+                 bullet_types, item_types, characters, nb_bullets_max):
         self.resource_loader = resource_loader
 
         self.bullet_types = bullet_types
+        self.item_types = item_types
         self.characters = characters
 
         self.bullets = []
+        self.items = []
         self.nb_bullets_max = nb_bullets_max
 
         self.stage = stage
@@ -43,13 +46,20 @@ class GameState(object):
         self.frame = 0
 
 
+    def change_bullets_into_star_items(self):
+        player = self.players[0] #TODO
+        item_type = self.item_types[6]
+        self.items.extend(Item((bullet.x, bullet.y), item_type, 0.0, item_type.speed, player, self) for bullet in self.bullets)
+        self.bullets = []
+
+
 
 class Game(object):
     def __init__(self, resource_loader, player_states, stage, rank, difficulty,
-                 bullet_types, characters, nb_bullets_max=None):
+                 bullet_types, item_types, characters, nb_bullets_max=None):
         self.game_state = GameState(resource_loader, player_states, stage,
                                     rank, difficulty,
-                                    bullet_types, characters, nb_bullets_max)
+                                    bullet_types, item_types, characters, nb_bullets_max)
 
         self.players = [Player(player_state, characters[player_state.character]) for player_state in player_states]
         self.enemies = []
@@ -94,6 +104,9 @@ class Game(object):
         for bullet in self.game_state.bullets:
             bullet.update()
 
+        for item in self.game_state.items:
+            item.update()
+
         # 4. Check for collisions!
         #TODO
         for player in self.players:
@@ -111,6 +124,9 @@ class Game(object):
                         or by2 < py1 or by1 > py2):
                     print('collided!') #TODO
 
+        #TODO: enemy-player collision
+        #TODO: item-player collision
+
         # 5. Cleaning
         self.cleanup()
 
--- a/pytouhou/game/games.py
+++ b/pytouhou/game/games.py
@@ -15,6 +15,7 @@
 from pytouhou.game.game import Game
 from pytouhou.game.character import Character
 from pytouhou.game.bullettype import BulletType
+from pytouhou.game.itemtype import ItemType
 
 class EoSDGame(Game):
     def __init__(self, resource_loader, players, stage, rank, difficulty):
@@ -30,6 +31,13 @@ class EoSDGame(Game):
                         BulletType(etama3, 7, 13, 20, 20, 20, hitbox_size=11),
                         BulletType(etama3, 8, 13, 20, 20, 20, hitbox_size=9),
                         BulletType(etama4, 0, 1, 2, 2, 2, hitbox_size=32)]
+        item_types = [ItemType(etama3, 0, 7,  speed=8., hitbox_size=42), #TODO: hitbox
+                      ItemType(etama3, 1, 8,  speed=8., hitbox_size=42), #TODO: hitbox
+                      ItemType(etama3, 2, 9,  speed=8., hitbox_size=42), #TODO: hitbox
+                      ItemType(etama3, 3, 10, speed=8., hitbox_size=42), #TODO: hitbox
+                      ItemType(etama3, 4, 11, speed=8., hitbox_size=42), #TODO: hitbox
+                      ItemType(etama3, 5, 12, speed=8., hitbox_size=42), #TODO: hitbox
+                      ItemType(etama3, 6, 13, speed=8., hitbox_size=42)] #TODO: hitbox
 
         player00 = resource_loader.get_anm_wrapper(('player00.anm',))
         player01 = resource_loader.get_anm_wrapper(('player01.anm',))
@@ -39,5 +47,5 @@ class EoSDGame(Game):
                       Character(player01, 5., 2.5, 2.5)]
 
         Game.__init__(self, resource_loader, players, stage, rank, difficulty,
-                      bullet_types, characters, nb_bullets_max=640)
+                      bullet_types, item_types, characters, nb_bullets_max=640)
 
new file mode 100644
--- /dev/null
+++ b/pytouhou/game/item.py
@@ -0,0 +1,52 @@
+# -*- encoding: utf-8 -*-
+##
+## Copyright (C) 2011 Thibaut Girka <thib@sitedethib.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published
+## by the Free Software Foundation; version 3 only.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+
+
+from math import cos, sin, atan2, pi
+
+
+class Item(object):
+    def __init__(self, pos, item_type, angle, speed, player, game_state):
+        self._game_state = game_state
+        self._sprite = item_type.sprite
+        self._removed = False
+        self._item_type = item_type
+
+        self.hitbox_half_size = item_type.hitbox_size / 2.
+
+        self.frame = 0
+
+        self.player = player
+
+        self.x, self.y = pos
+        self.angle = angle
+        self.speed = speed
+        dx, dy = cos(angle) * speed, sin(angle) * speed
+        self.delta = dx, dy
+
+        self._sprite.angle = angle
+
+
+    def update(self):
+        dx, dy = self.delta
+
+        if self.player is not None:
+            self.angle = atan2(self.player.y - self.y, self.player.x - self.x)
+            dx, dy = cos(self.angle) * self.speed, sin(self.angle) * self.speed
+        else:
+            pass #TODO: item falls!
+
+        self.x += dx
+        self.y += dy
+
new file mode 100644
--- /dev/null
+++ b/pytouhou/game/itemtype.py
@@ -0,0 +1,12 @@
+from pytouhou.game.sprite import Sprite
+
+class ItemType(object):
+    def __init__(self, anm_wrapper, sprite_index, indicator_sprite_index, speed,
+                 hitbox_size):
+        self.anm_wrapper = anm_wrapper
+        self.sprite = Sprite()
+        self.sprite.anm, self.sprite.texcoords = anm_wrapper.get_sprite(sprite_index)
+        self.indicator_sprite = Sprite()
+        self.indicator_sprite.anm, self.indicator_sprite.texcoords = anm_wrapper.get_sprite(indicator_sprite_index)
+        self.speed = speed
+        self.hitbox_size = hitbox_size
--- a/pytouhou/game/sprite.py
+++ b/pytouhou/game/sprite.py
@@ -27,7 +27,7 @@ class Sprite(object):
     def __init__(self, width_override=0, height_override=0):
         self.anm = None
         self._removed = False
-        self._changed = False
+        self._changed = True
 
         self.width_override = width_override
         self.height_override = height_override
--- a/pytouhou/opengl/gamerenderer.pyx
+++ b/pytouhou/opengl/gamerenderer.pyx
@@ -152,5 +152,7 @@ cdef class GameRenderer:
             self.render_elements(game.enemies)
             self.render_elements(game.players)
             self.render_elements(game.game_state.bullets)
+            self.render_elements(game.game_state.items)
+            #TODO: display item indicators
             glEnable(GL_FOG)
 
--- a/pytouhou/vm/eclrunner.py
+++ b/pytouhou/vm/eclrunner.py
@@ -658,6 +658,11 @@ class ECLRunner(object):
         self._enemy.extended_bullet_attributes = tuple(self._getval(attr) for attr in attributes)
 
 
+    @instruction(83)
+    def change_bullets_into_star_items(self):
+        self._game_state.change_bullets_into_star_items()
+
+
     @instruction(93)
     def set_spellcard(self, unknown, number, name):
         #TODO: display it on the game.