Skip to content
Snippets Groups Projects
Commit 861f945d authored by Weidong Yang's avatar Weidong Yang
Browse files

add mainScene and settingScene

parent 973742ba
No related branches found
No related tags found
1 merge request!1add mainScene and settingScene
from shape import Shape2D
from pyglet.gl import *
from pyglet.graphics import TextureGroup
class Button(object):
def __init__(self,x,y,width,height,text,textColor,quadColor):
self.x = x
self.y = y
self.width = width
self.height = height
self.textColor = textColor
self.quadColor = quadColor
self.function = None
self.text = text
self.label = pyglet.text.Label(text = text, font_name='Arial', font_size = 3 * height / 8,
x= x + width//2, y=y + height//2, anchor_x='center', anchor_y='center',
color=textColor)
self.quad = pyglet.graphics.vertex_list(4,
('v2i', Shape2D.quad_vertices(x,y,width,height)),
('c3B',quadColor*4))
def draw(self):
self.quad.draw(pyglet.gl.GL_QUADS)
self.label.draw()
def on_click(self,x,y):
if self._checkMouse(x,y):
func,args = self.function
func(*args)
def on_mouse(self,x,y,textColor,quadColor):
if self._checkMouse(x,y):
self.label.color = textColor
self.quad.colors = quadColor*4
else:
self.label.color = self.textColor
self.quad.colors = self.quadColor*4
def on_resize(self,x,y,width,height):
self.x = x
self.y = y
self.width = width
self.height = height
self.label.x = x + width//2
self.label.y = y + height//2
self.label.font_size = 3 * height / 8
self.quad.vertices = Shape2D.quad_vertices(x,y,width,height)
def changeFunc(self,func,*args):
self.function = (func, args)
def _checkMouse(self,x,y):
return x > self.x and x < self.x+self.width and y > self.y and y < self.y+self.height
def changeText(self,text):
self.label.text = text
class OnOffButton():
def __init__(self, x, y, width, height, LeftToRightFunc, RightToLeftFunc, textColor = (255,0,0,255),
quadColor = (0,0,0), slideQuadColor = (64,64,64),state = False, leftText = "OFF", rightText = "ON"):
##@param state Boolean, False represent left and True represents Right
# @param onFunc the tuple of (func, *args)
# @param offFunc the tuple of (func, *args)
self.x = x
self.y = y
self.width = width
self.height = height
self.state = state
self.LeftToRightFunc = LeftToRightFunc
self.RightToLeftFunc = RightToLeftFunc
self.leftText = pyglet.text.Label(text = leftText, font_name='Arial', font_size = 3 * height // 7,
x = x - width//2 -10, y=y, anchor_x='right', anchor_y='center',
color = textColor)
self.rightText = pyglet.text.Label(text = rightText, font_name='Arial', font_size = 3 * height // 7,
x= x + 10 + width//2, y = y, anchor_x='left', anchor_y='center',
color = textColor)
self.quad = pyglet.graphics.vertex_list(4,
('v2i', Shape2D.quad_vertices(x - width //2 ,y - height //2,width,height)),
('c3B',quadColor*4))
self.slideQuad = pyglet.graphics.vertex_list(4,
('v2i', Shape2D.quad_vertices(x - 3 * width//8,y - 5 * height //8,width//4, 5 * height// 4)),
('c3B',slideQuadColor*4))
def draw(self):
self.leftText.draw()
self.rightText.draw()
self.quad.draw(pyglet.gl.GL_QUADS)
self.slideQuad.draw(pyglet.gl.GL_QUADS)
def on_resize(self,x,y,width,height):
self.x = x
self.y = y
self.width = width
self.height = height
#leftText
self.leftText.x = x - width//2 -10
self.leftText.y = y
self.leftText.font_size = 3 * height // 7
#rightText
self.rightText.x = x + width//2 +10
self.rightText.y = y
self.rightText.font_size = 3 * height // 7
#quads
self.quad.vertices = Shape2D.quad_vertices(x - width //2 ,y - height //2,width,height)
#slideQuad
self.changeState(self.state)
def on_click(self,x,y):
if self._checkMouseOn(x,y):
if self.state:
func,args = self.RightToLeftFunc
else:
func,args = self.LeftToRightFunc
func(*args)
self.changeState(not self.state)
return True
return False
def changeState(self, state):
if state:
#change to True(Right)
self.slideQuad.vertices = Shape2D.quad_vertices(self.x + self.width//8, self.y - 5 * self.height //8, self.width//4, 5 * self.height// 4)
else:
#change to Left(True)
self.slideQuad.vertices = Shape2D.quad_vertices(self.x - 3 * self.width//8, self.y - 5 * self.height //8, self.width//4, 5 * self.height// 4)
self.state = state
def _checkMouseOn(self,x,y):
return self.x - self.width // 2 < x and x < self.x + self.width // 2 and self.y - self.height //2 < y and self.y < self.y + self.height //2
import math
class Creature(object):
def __init__(self, position, health,dy = 0, walkSpeed = 5, flying = False, flySpeed = 10, height = 1, jumpHeight = 1.0):
# 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 = position
# 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)
# 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]
# Velocity in the y (upward) direction.
self.dy = dy
#
self.walkSpeed = walkSpeed
#the height that creature can reach by jumping (default : About the height of a block)
self.JumpHeight = jumpHeight
#max falling velocity
self.terminalVelocity = 50
#weather creature are flying
self.flying = flying
#how fast could the creature fly
self.flySpeed = flySpeed
#the height of the creature
self.height = height
#the health of the creatures
self.health = health
def rotate(self,x,y):
y = max(-90, min(90, y))
self.rotation = (x, y)
def move(self,direction):
if direction == "FORWARD":
self.strafe[0] -= 1
elif direction == "BACKWARD":
self.strafe[0] += 1
elif direction == "LEFT":
self.strafe[1] -= 1
elif direction == "RIGHT":
self.strafe[1] += 1
else:
raise ValueError("The direction has to be forward, backward, left or right.")
def stopMove(self,direction):
if direction == "FORWARD":
self.strafe[0] += 1
elif direction == "BACKWARD":
self.strafe[0] -= 1
elif direction == "LEFT":
self.strafe[1] += 1
elif direction == "RIGHT":
self.strafe[1] -= 1
else:
raise ValueError("The direction has to be forward, backward, left or right.")
def jump(self,gravity):
# To derive the formula for calculating jump speed, first solve
# v_t = v_0 + a * t
# for the time at which you achieve maximum height, where a is the acceleration
# due to gravity and v_t = 0. This gives:
# t = - v_0 / a
# Use t and the desired MAX_JUMP_HEIGHT to solve for v_0 (jump speed) in
# s = s_0 + v_0 * t + (a * t^2) / 2
self.dy = math.sqrt(2 * gravity * self.JumpHeight)
def update(self,dt,world):
""" Private implementation of the `update()` method. This is where most
of the motion logic lives, along with gravity and collision detection.
Parameters
----------
dt : float
The change in time since the last call.
"""
# walking
speed = self.walkSpeed
d = dt * speed # distance covered this tick.
dx, dy, dz = self.get_motion_vector()
# New position in space, before accounting for gravity.
dx, dy, dz = dx * d, dy * d, dz * d
# gravity
if not self.flying:
# Update your vertical speed: if you are falling, speed up until you
# hit terminal velocity; if you are jumping, slow down until you
# start falling.
self.dy -= dt * world.gravity
self.dy = max(self.dy, - self.terminalVelocity)
dy += self.dy * dt
# collisions
x, y, z = self.position
x, y, z = world.collide((x + dx, y + dy, z + dz), self)
self.position = (x, y, z)
def get_motion_vector(self):
""" Returns the current motion vector indicating the velocity of the
creature.
Returns
-------
vector : tuple of len 3
Tuple containing the velocity in x, y, and z respectively.
"""
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)
from PIL import Image
import math,os
def MergePicture(width,height,pictures,folder, savePath):
if len(pictures) == 0: return
if type(savePath) != str or savePath == "": raise ValueError
toImage = Image.new('RGBA',(width,height))
num = int(round(math.sqrt(len(pictures))))
if math.sqrt(len(pictures)) > num:
mum += 1
for i in range(len(pictures)):
fromImge = Image.open(os.path.join(folder,pictures[i]))
img = fromImge.resize((width//num, height//num), Image.ANTIALIAS)
loc = ((i//num) * (width // num), (i % num) *(height // num))
toImage.paste(img, loc)
toImage.save(os.path.join(folder,savePath), quality=95)
if __name__ == '__main__':
arr = ["Grass_bottom.png","Grass_top.png","Grass_side.png"]
MergePicture(256,256,arr,"texture","Grass.png")
import sys,os
import math
import random
import time
from collections import deque
from pyglet import image
from pyglet.gl import *
from pyglet.graphics import TextureGroup
from pyglet.window import key, mouse
from block import Block
from screen import Screen
from loadSource import *
from shape import Shape3D
if sys.version_info[0] >= 3:
xrange = range
if sys.version_info[0] * 10 + sys.version_info[1] >= 38:
time.clock = time.process_time
class GameScene(Screen):
def __init__(self,game):
super(GameScene,self).__init__(game,True)
#
self.label = pyglet.text.Label('', font_name='Arial', font_size=18,
x=10, y=self.game.height - 10, anchor_x='left', anchor_y='top',
color=(255,255,255, 255))
##Initialize crosshairs and add it to the batch
self.reticle = None
# A list of blocks the player can place. Hit num keys to cycle.
self.inventory = [BRICK, GRASS, STONE]
# The current block the user can place. Hit num keys to cycle.
self.block = self.inventory[0]
# Convenience list of num keys.
self.num_keys = [
key._1, key._2, key._3, key._4, key._5,
key._6, key._7, key._8, key._9, key._0]
def mouseClick(self, x, y, button, modifiers):
if self.mouseExclusive:
vector = self.game.player.get_sight_vector()
curPos, prePos = self.game.world.hit_test(self.game.player.position, vector)
if (button == mouse.RIGHT) or \
((button == mouse.LEFT) and (modifiers & key.MOD_CTRL)):
# ON OSX, control + left click = right click.
if prePos:
self.game.world.add_block(prePos, self.block)
BUILDSOUND.play()
elif button == pyglet.window.mouse.LEFT and curPos:
block = self.game.world.world[curPos]
if block.destroyable == True:
self.game.world.remove_block(curPos)
DESTROYSOUND.play()
else:
self.game.set_exclusive_mouse(True)
def mouseMove(self, x, y, dx, dy):
if self.mouseExclusive:
#the sentivility of the mouse
m = 0.15
x, y = self.game.player.rotation
x, y = x + dx * m, y + dy * m
self.game.player.rotate(x,y)
def keyPressed(self, symbol, modifiers):
if symbol == key.W:
self.game.player.move("FORWARD")
elif symbol == key.S:
self.game.player.move("BACKWARD")
elif symbol == key.A:
self.game.player.move("LEFT")
elif symbol == key.D:
self.game.player.move("RIGHT")
elif symbol == key.SPACE:
if self.game.player.dy == 0:
self.game.player.jump(self.game.world.gravity)
elif symbol == key.ESCAPE:
self.game.changeScene('set')
elif symbol == key.TAB:
self.game.player.changeFlyState()
elif symbol in self.num_keys:
index = (symbol - self.num_keys[0]) % len(self.inventory)
self.block = self.inventory[index]
def keyRelease(self, symbol, modifiers):
if symbol == key.W:
self.game.player.stopMove("FORWARD")
elif symbol == key.S:
self.game.player.stopMove("BACKWARD")
elif symbol == key.A:
self.game.player.stopMove("LEFT")
elif symbol == key.D:
self.game.player.stopMove("RIGHT")
def screenResize(self, width, height):
""" Called when the window is resized to a new `width` and `height`.
"""
# label
self.label.y = height - 10
# reticle
if self.reticle:
self.reticle.delete()
x, y = self.game.width // 2, self.game.height // 2
n = 10
self.reticle = pyglet.graphics.vertex_list(4,
('v2i', (x - n, y, x + n, y, x, y - n, x, y + n))
)
def update(self, dt):
self.game.world.updateWorld(1.0/self.game.refreshRate,self.game.player)
m = 8
dt = min(dt, 0.2)
for _ in xrange(m):
self.game.player.update(dt/m,self.game.world)
def draw(self):
##set up the sky color
self._setBGColor(*self.game.world.skyColor())
self._setup_glbasic()
self._setup_fog(*self.game.world.skyColor(),20.0,60.0)
self._setup_3d(self.game.player.rotation, self.game.player.position)
glColor3d(1, 1, 1)
self.game.world.batch.draw()
self._drawFocusedBlock()
self._setup_2d()
self._draw_label()
self._draw_reticle()
def _draw_label(self):
""" Draw the label in the top left of the screen.
"""
x, y, z = self.game.player.position
self.label.text = '%02d (%.2f, %.2f, %.2f) %d / %d' % (
pyglet.clock.get_fps(), x, y, z,
len(self.game.world._shown), len(self.game.world.world))
self.label.draw()
def _draw_reticle(self):
""" Draw the crosshairs in the center of the screen.
"""
glColor3d(0, 0, 0)
self.reticle.draw(GL_LINES)
def _drawFocusedBlock(self):
""" Draw black edges around the block that is currently under the
crosshairs.
"""
vector = self.game.player.get_sight_vector()
block = self.game.world.hit_test(self.game.player.position, vector)[0]
if block:
x, y, z = block
vertex_data = Shape3D.cube_vertices(x, y, z, 0.51)
glColor3d(0, 0, 0)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
pyglet.graphics.draw(24, GL_QUADS, ('v3f/static', vertex_data))
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
from screen import Screen
from button import Button
class MainScene(Screen):
def __init__(self,game):
super(MainScene,self).__init__(game,False)
x,y = self.game.width, self.game.height
self.stage = {
"stage1":
[("start Game",self.changeStage,("stage2",)),
("Setting",self.game.changeScene,("set",)),
("Quit",self.game.close,())],
"stage2":
[("Start New Game",self.game.changeScene,("game",)),
("Load Game",self.changeStage,("stage3",)),
("Return",self.changeStage,("stage1",))],
"stage3":
[("Game one",print,("loading game1",)),
("Game two",print,("loading game2",)),
("Return",self.changeStage,("stage2",))]
}
self.button1 = Button(x//4,y//2,x//2,y//8,"",(255,255,255,255),(0,0,0))
self.button2 = Button(x//4,(11*y)//32,x//2,y//8,"",(255,255,255,255),(0,0,0))
self.button3 = Button(x//4,(3*y)//16,x//2,y//8,"",(255,255,255,255),(0,0,0))
self.buttons = [self.button1,self.button2,self.button3]
self.changeStage("stage1")
def mouseClick(self, x, y, button, modifiers):
for butt in self.buttons:
if butt.on_click(x,y):
return
def mouseMove(self,x, y, dx, dy):
for butt in self.buttons:
butt.on_mouse(x,y,(0,255,0,255),(255,255,255))
def screenResize(self,width, height):
x,y = width, height
self.button1.on_resize(x//4,y//2,x//2,y//8)
self.button2.on_resize(x//4,(11*y)//32,x//2,y//8)
self.button3.on_resize(x//4,(3*y)//16,x//2,y//8)
def draw(self):
self._setBGColor(*self.game.world.skyColor())
self._setup_glbasic()
self._setup_2d()
self.button1.draw()
self.button2.draw()
self.button3.draw()
def changeStage(self,stage):
if stage in self.stage.keys():
but = self.stage[stage]
for i in range(len(self.buttons)):
self.buttons[i].changeText(but[i][0])
self.buttons[i].changeFunc(but[i][1],*but[i][2])
import math
from creature import Creature
class Player(Creature):
def __init__(self,position,):
super(Player,self).__init__(position = position, height = 2, health = 100)
self.energy = 100
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)
from collections import deque
import time
class ProcessQueue(object):
def __init__(self):
self.queue = deque()
def enqueue(self, func, *args):
""" Add `func` to the internal queue.
"""
self.queue.append((func, args))
def dequeue(self):
""" Pop the top function from the internal queue and call it.
"""
func, args = self.queue.popleft()
func(*args)
def process_queue(self,maxPeriod):
""" Process the entire queue while taking periodic breaks. This allows
the game loop to run smoothly.
"""
start = time.clock()
while self.queue and time.clock() - start < maxPeriod:
self.dequeue()
def process_entire_queue(self):
""" Process the entire queue with no breaks.
"""
while self.queue:
self.dequeue()
import math
from pyglet.gl import *
from pyglet.graphics import TextureGroup
from shape import Shape2D
class Screen(object):
def __init__(self,game, exclusive):
self.game = game
# Whether or not the window exclusively captures the mouse.
self.mouseExclusive = exclusive
def mouseClick(self, x, y, button, modifiers):
pass
def update(self, dt):
pass
def mouseMove(x, y, dx, dy):
pass
def keyPressed(symbol, modifiers):
pass
def keyRelease(symbol, modifiers):
pass
def screenResize(width, height):
pass
def draw():
pass
def _setBGColor(self,R,G,B,A):
glClearColor(R, G, B, A)
def _setup_fog(self, R, G, B, A,start,end):
""" Configure the OpenGL fog properties.
"""
# Enable fog. Fog "blends a fog color with each rasterized pixel fragment's
# post-texturing color."
glEnable(GL_FOG)
# Set the fog color.
glFogfv(GL_FOG_COLOR, (GLfloat * 4)(R, G, B, A))
# Say we have no preference between rendering speed and quality.
glHint(GL_FOG_HINT, GL_DONT_CARE)
# Specify the equation used to compute the blending factor.
glFogi(GL_FOG_MODE, GL_LINEAR)
# How close and far away fog starts and ends. The closer the start and end,
# the denser the fog in the fog range.
glFogf(GL_FOG_START, start)
glFogf(GL_FOG_END, end)
def _setup_glbasic(self):
""" Basic OpenGL configuration.
"""
# Enable culling (not rendering) of back-facing facets -- facets that aren't
# visible to you.
glEnable(GL_CULL_FACE)
# Set the texture minification/magnification function to GL_NEAREST (nearest
# in Manhattan distance) to the specified texture coordinates. GL_NEAREST
# "is generally faster than GL_LINEAR, but it can produce textured images
# with sharper edges because the transition between texture elements is not
# as smooth."
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
def _setup_2d(self):
""" Configure OpenGL to draw in 2d.
"""
width, height = self.game.get_size()
glDisable(GL_DEPTH_TEST)
viewport = self.game.get_viewport_size()
glViewport(0, 0, max(1, viewport[0]), max(1, viewport[1]))
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, max(1, width), 0, max(1, height), -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def _setup_3d(self,rotation,position):
""" Configure OpenGL to draw in 3d.
@param rotation tuple of (x,y) representing the the rotation angle in the z-axis down and the ground up
@param position tuple of (x,y,z) representing the position of the view
"""
width, height = self.game.get_size()
glEnable(GL_DEPTH_TEST)
viewport = self.game.get_viewport_size()
glViewport(0, 0, max(1, viewport[0]), max(1, viewport[1]))
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(65.0, width / float(height), 0.1, 60.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
x, y = rotation
glRotatef(x, 0, 1, 0)
glRotatef(-y, math.cos(math.radians(x)), 0, math.sin(math.radians(x)))
x, y, z = position
glTranslatef(-x, -y, -z)
from screen import Screen
from button import OnOffButton,Button
class SettingScene(Screen):
def __init__(self,game):
super(SettingScene,self).__init__(game,False)
## a list of tuple (x,y,width,height,color)bbh
x,y = self.game.width, self.game.height
self.mode = OnOffButton(x//2,y//2,x//8,y//6,(self.game.world.changeMode,("night",)),(self.game.world.changeMode,("day",)),leftText = "Day",rightText = "Night")
self.returnBut = Button(20,y-70,100,50,"Return",(255,255,255,255),(0,0,0))
self.returnBut.changeFunc(self.game.goBack)
self.mainBut = Button(200,50,200,50,"Save and Return",(255,255,255,255),(0,0,0))
self.mainBut.changeFunc(self.game.changeScene,"main")
def screenResize(self,width, height):
self.mode.on_resize(width//2,height//2,width//8,height//8)
self.returnBut.on_resize(20,height-70,100,50)
self.mainBut.on_resize(200,50,200,50)
def draw(self):
self._setBGColor(*self.game.world.skyColor())
self._setup_glbasic()
self._setup_2d()
self.mode.draw()
self.returnBut.draw()
self.mainBut.draw()
def update(self,dt):
pass
def mouseMove(self, x, y, dx, dy):
self.returnBut.on_mouse(x,y,(0,255,0,255),(255,255,255))
self.mainBut.on_mouse(x,y,(0,255,0,255),(255,255,255))
def mouseClick(self, x, y, button, modifiers):
self.mode.on_click(x,y)
self.returnBut.on_click(x,y)
self.mainBut.on_click(x,y)
def keyPressed(self, symbol, modifiers):
pass
def keyRelease(self, symbol, modifiers):
pass
def drawButton(self,text,width, height):
pass
class Shape3D(object):
def cube_vertices(x, y, z, n):
""" Return the vertices of the cube at position x, y, z with size 2*n.
"""
return [
x-n,y+n,z-n, x-n,y+n,z+n, x+n,y+n,z+n, x+n,y+n,z-n, # top
x-n,y-n,z-n, x+n,y-n,z-n, x+n,y-n,z+n, x-n,y-n,z+n, # bottom
x-n,y-n,z-n, x-n,y-n,z+n, x-n,y+n,z+n, x-n,y+n,z-n, # left
x+n,y-n,z+n, x+n,y-n,z-n, x+n,y+n,z-n, x+n,y+n,z+n, # right
x-n,y-n,z+n, x+n,y-n,z+n, x+n,y+n,z+n, x-n,y+n,z+n, # front
x+n,y-n,z-n, x-n,y-n,z-n, x-n,y+n,z-n, x+n,y+n,z-n, # back
]
class Shape2D(object):
def quad_vertices(x, y, w, h):
return [
x,y, x+w,y,
x+w,y+h, x,y+h,
]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment