Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update on input fixes #61

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ple/games/flappybird/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ def __init__(self,
self.image.set_colorkey((0, 0, 0))

self.init(gap_start, gap_size, offset, color)
assert gap_size >=30, "Gap size not big enough!" #check if the bird can't fly through the pipes. Update to adjust after testing if needed

def init(self, gap_start, gap_size, offset, color):
self.image.fill((0, 0, 0))
Expand Down
13 changes: 11 additions & 2 deletions ple/games/pixelcopter.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ class Pixelcopter(PyGameWrapper):
"""

def __init__(self, width=48, height=48):
assert 0<width<2000 , "Invalid Width Size: "+str(width)
assert 0<height<2000 , "Invalid Width Size: "+str(height)

actions = {
"up": K_w
}
Expand Down Expand Up @@ -256,9 +259,15 @@ def _add_terrain(self, start, end):
def _add_blocks(self):
x_pos = self.rng.randint(self.width, int(self.width * 1.5))
y_pos = self.rng.randint(
int(self.height * 0.25),
int(self.height * 0.75)
int(self.height * -0.25),
int(self.height * 0.25)
)
if y_pos<0:
y_pos-=int(self.height * 0.10)
if y_pos>0:
y_pos+=int(self.height * 0.10)
y_pos+=int(self.height * 0.50)

self.block_group.add(
Block(
(x_pos, y_pos),
Expand Down
51 changes: 23 additions & 28 deletions ple/games/pong.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import math
import sys

import pygame
import pygame, pygame.sprite
from pygame.constants import K_w, K_s
from ple.games.utils.vec2d import vec2d
from ple.games.utils import percent_round_int
Expand Down Expand Up @@ -42,40 +42,28 @@ def __init__(self, radius, speed, rng,
self.rect = self.image.get_rect()
self.rect.center = pos_init

def line_intersection(self, p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y):

s1_x = p1_x - p0_x
s1_y = p1_y - p0_y
s2_x = p3_x - p2_x
s2_y = p3_y - p2_y

s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y)
t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y)

return (s >= 0 and s <= 1 and t >= 0 and t <= 1)

def update(self, agentPlayer, cpuPlayer, dt):

self.pos.x += self.vel.x * dt
self.pos.y += self.vel.y * dt

is_pad_hit = False

if self.pos.x <= agentPlayer.pos.x + agentPlayer.rect_width:
if self.line_intersection(self.pos_before.x, self.pos_before.y, self.pos.x, self.pos.y, agentPlayer.pos.x + agentPlayer.rect_width / 2, agentPlayer.pos.y - agentPlayer.rect_height / 2, agentPlayer.pos.x + agentPlayer.rect_width / 2, agentPlayer.pos.y + agentPlayer.rect_height / 2):
self.pos.x = max(0, self.pos.x)
self.vel.x = -1 * (self.vel.x + self.speed * 0.05)
self.vel.y += agentPlayer.vel.y * 2.0
self.pos.x += self.radius
is_pad_hit = True

if self.pos.x >= cpuPlayer.pos.x - cpuPlayer.rect_width:
if self.line_intersection(self.pos_before.x, self.pos_before.y, self.pos.x, self.pos.y, cpuPlayer.pos.x - cpuPlayer.rect_width / 2, cpuPlayer.pos.y - cpuPlayer.rect_height / 2, cpuPlayer.pos.x - cpuPlayer.rect_width / 2, cpuPlayer.pos.y + cpuPlayer.rect_height / 2):
self.pos.x = min(self.SCREEN_WIDTH, self.pos.x)
self.vel.x = -1 * (self.vel.x + self.speed * 0.05)
self.vel.y += cpuPlayer.vel.y * 0.006
self.pos.x -= self.radius
is_pad_hit = True
#Using pygame collision detection, we can pass in the objects directly, first the player
if pygame.sprite.collide_rect(self, agentPlayer):
self.pos.x = max(0, self.pos.x)
self.vel.x = -1 * (self.vel.x + self.speed * 0.05)
self.vel.y += agentPlayer.vel.y * 2.0
self.pos.x += self.radius
is_pad_hit = True

#then we test the cpu, much cleaner!
if pygame.sprite.collide_rect(self, cpuPlayer):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you verify that this does not slow down the step speed? I believe using this function was slower.

self.pos.x = min(self.SCREEN_WIDTH, self.pos.x)
self.vel.x = -1 * (self.vel.x + self.speed * 0.05)
self.vel.y += cpuPlayer.vel.y * 0.006
self.pos.x -= self.radius
is_pad_hit = True

# Little randomness in order not to stuck in a static loop
if is_pad_hit:
Expand Down Expand Up @@ -196,6 +184,13 @@ class Pong(PyGameWrapper):

def __init__(self, width=64, height=48, cpu_speed_ratio=0.6, players_speed_ratio = 0.4, ball_speed_ratio=0.75, MAX_SCORE=11):

assert width > 0, "Error: width must be greater than 0"
assert height > 0, "Error: height must be greater than 0"
assert cpu_speed_ratio > 0, "Error: cpu_speed_ratio must be greater than 0"
assert players_speed_ratio > 0, "Error: player_speed_ratio must be greater than 0"
assert ball_speed_ratio > 0, "Error: ball_speed_ration must be greater than 0"
assert MAX_SCORE > 0, "Error: MAX_SCORE must be greater than 0"

actions = {
"up": K_w,
"down": K_s
Expand Down
10 changes: 6 additions & 4 deletions ple/games/puckworld.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ def __init__(self,
width=64,
height=64):

assert 0<width<2000 , "Invalid Width Size: "+str(width)
assert 0<height<2000 , "Invalid Width Size: "+str(height)

actions = {
"up": K_w,
"left": K_a,
Expand Down Expand Up @@ -216,7 +219,7 @@ def init(self):
self.creeps = pygame.sprite.Group()
self.creeps.add(self.good_creep)
self.creeps.add(self.bad_creep)

self.creeps.add(self.player)
self.score = 0
self.ticks = 0
self.lives = -1
Expand Down Expand Up @@ -245,8 +248,7 @@ def step(self, dt):
reward = -dist_to_good
if dist_to_bad < self.CREEP_BAD['radius_outer']:
reward += 2.0 * \
(dist_to_bad - self.CREEP_BAD['radius_outer']
) / float(self.CREEP_BAD['radius_outer'])
(dist_to_bad - self.CREEP_BAD['radius_outer'])

self.score += reward

Expand All @@ -261,7 +263,7 @@ def step(self, dt):
self.bad_creep.update(ndx, ndy, dt)
self.good_creep.update(dt)

self.player.draw(self.screen)
#self.player.draw(self.screen)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this commented out?

self.creeps.draw(self.screen)


Expand Down
10 changes: 9 additions & 1 deletion ple/games/raycastmaze.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,15 @@ def __init__(self,
move_speed=20, turn_speed=13,
map_size=10, height=48, width=48, init_pos_distance_to_target=None):

assert map_size > 5, "map_size must be gte 5"
for x in init_pos:
assert (x >= 0) and (x < map_size), "Error: init_pos must be on the map (0 to map_size)"
assert resolution > 0, "Error: resolution must be greater than 0"
assert move_speed > 0, "Error: move_speed must be greater than 0"
assert move_speed < 100, "Error: move_speed must be less than 100"
assert turn_speed > 0, "Error: turn_speed must be greater than 0"
assert turn_speed < 100, "Error: turn_speed must be less than 100"
assert (map_size > 5) and (map_size <= 100), "Error: map_size must be >= 5 and <= 100"
assert (height > 0) and (width > 0) and (height == width), "Error: height and width must be equal and greater than 0"

# do not change
init_dir = (1.0, 0.0)
Expand Down
4 changes: 3 additions & 1 deletion ple/ple.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import numpy as np
from PIL import Image # pillow
import sys

from time import sleep
import pygame
from .games.base.pygamewrapper import PyGameWrapper

Expand Down Expand Up @@ -373,6 +373,8 @@ def act(self, action):
Returns the reward that the agent has accumlated while performing the action.

"""
if self.display_screen:
sleep(1/float(self.fps))
return sum(self._oneStepAct(action) for i in range(self.frame_skip))

def _draw_frame(self):
Expand Down
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mock==1.0.1
numpydoc
Sphinx==1.2.3
sphinx_rtd_theme
sphinx_rtd_theme
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pygame
24 changes: 12 additions & 12 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,23 @@
]

setup(
name='ple',
version='0.0.1',
description='PyGame Learning Environment',
name='ple',
version='0.0.1',
description='PyGame Learning Environment',
classifiers=[
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 2.7",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
],
url='https://github.com/ntasfi/PyGame-Learning-Environment',
author='Norman Tasfi',
author_email='first letter of first name plus last at googles email service.',
keywords='',
license="MIT",
packages=find_packages(),
include_package_data=False,
zip_safe=False,
install_requires=install_requires
url='https://github.com/ntasfi/PyGame-Learning-Environment',
author='Norman Tasfi',
author_email='first letter of first name plus last at googles email service.',
keywords='',
license="MIT",
packages=find_packages(),
include_package_data=False,
zip_safe=False,
install_requires=install_requires
)
34 changes: 34 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from ple import PLE
from ple.games.pong import Pong
import pygame
import time
import sys

game = Pong(width=300, height=200)

p = PLE(game, fps=30, display_screen=True, force_fps=True)
p.init()

print(p.getActionSet())

nb_frames = 1000
action = None

for f in range(nb_frames):
if p.game_over():
p.reset_game()
obs = p.getScreenRGB()
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key:
action = event.key
print(action)
elif event.type == pygame.KEYUP:
action = None
p.act(action)
time.sleep(.05)

#This is a change
51 changes: 51 additions & 0 deletions tests/test_pong.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/python
from ple import PLE
from ple.games.pong import Pong, Ball, Player
import pygame, time, sys, pytest

#This test passes if a positive difference in movement speed is detected
def test_movement_up():
game=Pong()
p=PLE(game, display_screen=True, fps=20, force_fps=1)
p.init()
time.sleep(.5)
oldState=p.getGameState()
p.act(game.actions["up"])
newState=p.getGameState()
assert oldState["player_velocity"] > newState["player_velocity"]

#This tests passes is a negative difference in movement speed is detected
def test_movement_down():
game=Pong()
p=PLE(game, display_screen=True, fps=20, force_fps=1)
p.init()
time.sleep(.5)
oldState=p.getGameState()
p.act(game.actions["down"])
newState=p.getGameState()
assert oldState["player_velocity"] < newState["player_velocity"]

#This test passes if an exception is thrown when a negative cpu speed is specified
def test_negative_cpu_speed():
with pytest.raises(Exception):
game=Pong(cpu_speed_ratio=-1)

#This test passes if an exception is thrown when a negative player speed is specified
def test_negative_player_speed():
with pytest.raises(Exception):
game=Pong(players_speed_ratio=-1)

#This test passes if an exception is thrown when a negative ball speed is specified
def test_negative_ball_speed():
with pytest.raises(Exception):
game=Pong(ball_speed_ratio=-1)

#This test passes if an exception is thrown when a negative game size is specified
def test_invalid_game_size():
with pytest.raises(Exception):
game=Pong(width=-200, height=-200)

#This test passes if an exception is thrown when a negative max score is specified
def test_invalid_max_score():
with pytest.raises(Exception):
game=Pong(MAX_SCORE=-1)
39 changes: 39 additions & 0 deletions tests/test_raycastmaze.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/python
from ple import PLE
from ple.games.raycastmaze import RaycastMaze
import pygame, time, sys, pytest

#This test passes if an exception is thrown when a negative initial position is specified
def test_oob_init_pos():
with pytest.raises(Exception):
game=RaycastMaze(init_pos=(-1,-1))

#This test passes if an exception is thrown when the map size is below the minimum for the algorithm (5)
def test_below_min_map_size():
with pytest.raises(Exception):
game=RaycastMaze(map_size=3)

#This test passes if an exception is thrown when a large map size is specified
def test_beyond_max_map_size():
with pytest.raises(Exception):
game=RaycastMaze(map_size=400)

#This test passes if an exception is thrown when a negative move speed is specified
def test_negative_move_speed():
with pytest.raises(Exception):
game=RaycastMaze(move_speed=-1)

#This test passes if an exception is thrown when a negative turn speed is specified
def test_negative_turn_speed():
with pytest.raises(Exception):
game=RaycastMaze(turn_speed=-1)

#This test passes if an exception is thrown when a non-usefully large turn speed is specified
def test_beyond_max_turn_speed():
with pytest.raises(Exception):
game=RaycastMaze(turn_speed=400)

#This test passes if an exception is thrown when a negative window size is specified
def test_negative_game_size():
with pytest.raises(Exception):
game=RaycastMaze(width=-100,height=-100)