-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPlayer.py
239 lines (188 loc) · 7.66 KB
/
Player.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
import time
import pyglet
import math
import random
from game_globals import *
import Action
class Player:
def __init__(self):
# A list of blocks the player can place. Hit num keys to cycle.
#self.inventory = [BRICK, GRASS, SAND]
self.game = None
# When flying gravity has no effect and speed is increased.
self.flying = False
# Current (x, y, z) position in the world, specified with floats. Note
# that, perhaps unlike in math class, the y-axis is the vertical axis.
self.position = (0, 0, 0)
# First element is rotation of the player in the x-z plane (ground
# plane) measured from the z-axis down. The second is the rotation
# angle from the ground plane up. Rotation is in degrees.
#
# The vertical plane rotation ranges from -90 (looking straight down) to
# 90 (looking straight up). The horizontal rotation range is unbounded.
self.rotation = (0, 0)
# Looking up/down or left/right?
self.looking = [0, 0]
# Strafing is moving lateral to the direction you are facing,
# e.g. moving to the left or right while continuing to face forward.
#
# First element is -1 when moving forward, 1 when moving back, and 0
# otherwise. The second element is -1 when moving left, 1 when moving
# right, and 0 otherwise.
self.strafe = [0, 0]
self.jump = False
self.dy = 0
# A list of blocks the player can place. Hit num keys to cycle.
#self.inventory = [BRICK, GRASS, SAND]
# The current block the user can place. Hit num keys to cycle.
#self.block = self.inventory[0]
self.previous_reward = 0.0
self.actions_performed = 0
self.rewards = {
"GRASS":1000,
"STONE":-10
}
self.total_score = 0
def setGame(self, game):
self.game = game
def get_sight_vector(self):
""" Returns the current line of sight vector indicating the direction
the player is looking.
"""
x, y = self.rotation
# y ranges from -90 to 90, or -pi/2 to pi/2, so m ranges from 0 to 1 and
# is 1 when looking ahead parallel to the ground and 0 when looking
# straight up or down.
m = math.cos(math.radians(y))
# dy ranges from -1 to 1 and is -1 when looking straight down and 1 when
# looking straight up.
dy = math.sin(math.radians(y))
dx = math.cos(math.radians(x - 90)) * m
dz = math.sin(math.radians(x - 90)) * m
return (dx, dy, dz)
def canJump(self):
height = PLAYER_HEIGHT
pad = 0.25
p = list(self.position)
np = normalize(self.position)
for face in FACES: # check all surrounding blocks
for i in xrange(3): # check each dimension independently
if not face[i]:
continue
# How much overlap you have with this dimension.
d = (p[i] - np[i]) * face[i]
if d < pad:
continue
for dy in xrange(height): # check each height
op = list(np)
op[1] -= dy
op[i] += face[i]
if tuple(op) not in self.game.world:
continue
p[i] -= (d - pad) * face[i]
if face == (0, -1, 0):
# You are colliding with the ground or ceiling, so stop
# falling / rising.
return True
break
return False
def get_motion_vector(self):
""" Returns the current motion vector indicating the velocity of the
player.
Returns
-------
vector : tuple of len 3
Tuple containing the velocity in x, y, and z respectively.
"""
self.simulate_look(0, 0, self.looking[0], self.looking[1])
if self.jump and self.canJump():
self.jump = False
self.dy = JUMP_SPEED
if any(self.strafe):
x, y = self.rotation
strafe = math.degrees(math.atan2(*self.strafe))
y_angle = math.radians(y)
x_angle = math.radians(x + strafe)
if self.flying:
m = math.cos(y_angle)
dy = math.sin(y_angle)
if self.strafe[1]:
# Moving left or right.
dy = 0.0
m = 1
if self.strafe[0] > 0:
# Moving backwards.
dy *= -1
# When you are flying up or down, you have less left and right
# motion.
dx = math.cos(x_angle) * m
dz = math.sin(x_angle) * m
else:
dy = 0.0
dx = math.cos(x_angle)
dz = math.sin(x_angle)
else:
dy = 0.0
dx = 0.0
dz = 0.0
return (dx, dy, dz)
def get_foot_position(self):
return int(self.position[0]), int(self.position[1]-1), int(self.position[2])
def get_head_position(self):
return int(self.position[0]), int(self.position[1]-1)+1, int(self.position[2])
#def on_mouse_motion(self, x, y, dx, dy):
def simulate_look(self, x, y, dx, dy):
""" Called when the player moves the mouse.
Parameters
----------
x, y : int
The coordinates of the mouse click. Always center of the screen if
the mouse is captured.
dx, dy : float
The movement of the mouse.
"""
m = 0.15
x, y = self.rotation
x, y = x + dx * m, y + -dy * m
y = max(-90, min(90, y))
self.rotation = (x, y)
def simulate_click(self):
vector = self.get_sight_vector()
block, previous = self.game.model.hit_test(self.position, vector)
#self.game.add_block(previous, self.block)
if block:
texture = self.game.model.world[block]
if texture == GRASS:
#print "REMOVING BLOCK"
self.game.model.remove_block(block)
return "GRASS"
if texture == STONE:
return "STONE"
else:
return ""
# Perform an action by setting the agent's movement fields to the values from the action object
def performAction(self, a):
self.actions_performed += 1
# Initialize a new reward for this current action
# There is a set cost of 1 for each move
reward = 0
# Each part of the action might have a cost or reward
# E.g. Moving might have an energy cost
# E.g. Breaking blocks might be good or bad; reward or penalty
self.strafe[0] = a.forwardbackward_walk
self.strafe[1] = a.leftright_walk
self.looking[0] = a.leftright_rotation
self.looking[1] = a.updown_rotation
# Try to break a block at the crosshairs
# Returns either the type of block broken/tried to break or None for no blocks in range
if a.break_block:
block_type = self.simulate_click()
if block_type != "":
reward += self.rewards[block_type]
self.previous_reward = reward
def getDecision(self, frame):
a = Action.getRandomAction()
self.performAction(a)
def save(self):
# Nothing to save for superclass
pass