1

I am working on a simulation for a business problem, but I am trying to build a 2d game to demonstrate the simulated movements.

To do this, I am starting off with an actual python game that I found some code for online.

The goal is to create 100s of simulated movements (up, down, left, right, stop) via random integer. For example, random = 1, then move left.

For some reason I am able to send the first movement, but the second to 100th movements are ignored by the game.

Can someone please give me a hint as to what I'm doing wrong?

I would greatly appreciate someone's expertise.

GitHub Link :: https://github.com/deacons2016/pygame

from __future__ import division

import random
from cocos.actions import AccelDeccel
from cocos.actions import Delay
from cocos.actions import JumpBy
from cocos.actions import Move
from cocos.actions import MoveBy
from cocos.actions import Repeat
from cocos.actions import Reverse
from cocos.actions import RotateBy
from pyglet.window import key

import cocos
import cocos.collision_model as cm
import resources
import time


class Game(cocos.layer.ColorLayer):
    is_event_handler = True

    def __init__(self):
        super(Game, self).__init__(102, 102, 225, 255)

        self.collision_manager = cm.CollisionManagerBruteForce()

        self.player = cocos.sprite.Sprite(resources.player)
        self.player.position = 400, 25
        self.player.velocity = 0, 0
        self.player.speed = 150
        self.add(self.player, z=2)

        self.player.cshape = cm.AARectShape(
            self.player.position,
            self.player.width//2,
            self.player.height//2
        )
        self.collision_manager.add(self.player)

        self.boss = cocos.sprite.Sprite(resources.player)
        self.boss.position = 400, 600
        self.boss.scale = 0.4
        self.add(self.boss, z=1)

        self.boss.cshape = cm.AARectShape(
            self.boss.position,
            self.boss.width//2,
            self.boss.height//2
        )
        self.collision_manager.add(self.boss)

        self.batch = cocos.batch.BatchNode()
        self.enemies = [cocos.sprite.Sprite(resources.player)
                        for i in range(6)]
        positions = ((250, 125), (550, 125), (300, 325), (500, 325),
                     (150, 475), (650, 475))
        for num, enem in enumerate(self.enemies):
            enem.position = positions[num]
            enem.cshape = cm.AARectShape(
                enem.position,
                enem.width//2,
                enem.height//2
            )
            self.collision_manager.add(enem)
            self.batch.add(enem)

        self.add(self.batch, z=1)
        self.player.do(Move())

        move_basic = MoveBy((120, 0), 1)
        self.enemies[0].do(Repeat(move_basic + Reverse(move_basic)))
        self.enemies[1].do(Repeat(Reverse(move_basic) + move_basic))

        move_complex = (MoveBy((-75, 75), 1) +
                        Delay(0.5) +
                        MoveBy((-75, -75), 1) +
                        Delay(0.5) +
                        MoveBy((75, -75), 1) +
                        Delay(0.5) +
                        MoveBy((75, 75), 1) +
                        Delay(0.5))
        self.enemies[2].do(Repeat(move_complex))
        self.enemies[3].do(Repeat(Reverse(move_complex)))

        move_jump = AccelDeccel(JumpBy((200, 0), 75, 3, 3))
        move_jump_rot = AccelDeccel(RotateBy(360, 3))
        self.enemies[4].do(Repeat(move_jump + Reverse(move_jump)))
        self.enemies[4].do(Repeat(move_jump_rot + Reverse(move_jump_rot)))
        self.enemies[5].do(Repeat(Reverse(move_jump) + move_jump))
        self.enemies[5].do(Repeat(Reverse(move_jump_rot) + move_jump_rot))

        self.schedule(self.update)

    def simulate(self):
        x = 100
        while x > 0:
            rand = random.randint(1,5)
            if rand == 1:
                self.movePlayer("left")
                time.sleep(.05)
                print("left")
            elif rand == 2:
                self.movePlayer("right")
                time.sleep(.05)
                print("right")
            elif rand == 3:
                self.movePlayer("up")
                time.sleep(.05)
                print("up")
            elif rand == 4:
                self.movePlayer("down")
                time.sleep(.05)
                print("down")

            elif rand == 5:
                self.movePlayer("space")
                time.sleep(.05)
                print("space")
            x -= 1

    def update(self, dt):
        self.player.cshape.center = self.player.position
        for enem in self.enemies:
            enem.cshape.center = enem.position

        collisions = self.collision_manager.objs_colliding(self.player)
        if collisions:
            if self.boss in collisions:
                print("You won!")
            cocos.director.director.pop()

    def movePlayer(self, symbol):

         if symbol == "left":
                self.player.velocity = -self.player.speed, 0
         elif symbol == "right":
                self.player.velocity = self.player.speed, 0
         elif symbol == "up":
                self.player.velocity = 0, self.player.speed
         elif symbol == "down":
                self.player.velocity = 0, -self.player.speed
         elif symbol == "space":
                self.player.velocity = 0, 0


if __name__ == '__main__':
    cocos.director.director.init(
        width=800,
        height=650,
        caption="Catch your husband!"
    )

    game_layer = Game()
    game_scene = cocos.scene.Scene(game_layer)

    game_layer.simulate()

    cocos.director.director.run(game_scene)

    print("after")
Leistungsabfall
  • 6,368
  • 7
  • 33
  • 41
Rupert
  • 4,209
  • 7
  • 31
  • 36
  • What's up with `direction`? You set it to an empty string, which has no effect in the method `movePlayer`, you don't reassign it to anything, yet you print it every time. – Reti43 Dec 12 '15 at 19:56
  • @Reti43 thx for the catch - i removed it, but i'm still getting the same results. – Rupert Dec 12 '15 at 19:59
  • I'm not surprised, as it shouldn't have any effect on the program. I just asked in case you were planning for it to have some effect. Can you also explain the line `self.schedule(self.update)`? It doesn't make sense to me. – Reti43 Dec 12 '15 at 20:18
  • checks for collisions on each frame – Rupert Dec 12 '15 at 20:21
  • Well, all I see you doing is a loop where you choose a direction 100 times and then send that argument to the `movePlayer()` method, which only updates your velocity vector. Unless the player's position is updated automatically when you change his velocity, I don't see any "movement" here. – Reti43 Dec 12 '15 at 20:24
  • it is updated automatically when teh velocity is changed – Rupert Dec 12 '15 at 20:51
  • I'm not familiar with the specifics of the `cocos` event loop, but I'd guess that it doesn't start actually running anything until you call `cocos.director.director.run(game_scene)`. Since that only happens after all your 100 velocity changes have been completed, you probably only see the effects of the last-chosen velocity. I suspect you want either to schedule your simulation function to be called somehow, or make it part of the `update` method which is already being run regularly (every frame?). – Blckknght Dec 13 '15 at 03:12
  • You're exactly right. Just not sure what to do next to fix it – Rupert Dec 13 '15 at 03:14

1 Answers1

1

Like @Blckknght pointed out, drawing the layer Game and running its other scheduled functions (in your case Game.update) starts only after calling cocos.director.director.run(game_scene). That is why you cannot see the velocity updates - they are done by the time drawing begins.

You should remove the call game_layer.simulate() as it doesn't have the desired effect.

Then you could do:

def simulate(self, dt):
    if self.x > 0:  # set this to 100 in constructor
        rand = random.randint(1,5)
        if rand == 1:
            self.movePlayer("left")
            print("left")
        elif rand == 2:
            self.movePlayer("right")
            print("right")
        elif rand == 3:
            self.movePlayer("up")
            print("up")
        elif rand == 4:
            self.movePlayer("down")
            print("down")

        elif rand == 5:
            self.movePlayer("space")
            print("space")
        x -= 1

Notice that I removed calls to time.sleep. Not sure if those would cause problems, but it's probably better to call the dedicated schedule_interval (or schedule) function in cocos2d.

In the constructor of Game:

self.schedule_interval(self.simulate, 0.05)
self.schedule_interval(self.update, 0.05)

To schedule Game.simulate you must change the signature of the function to have dt as its second argument, like Game.update has.