Pong
godot 的源码目录 demos中带来好多游戏demo,这里只介绍在2D游戏中基本的函数使用。
添加一个Node2D节点,Node2D是一个基础类型在2D引擎中。在这之后添加Sprite node,并且每一个Sprite node 都在Texture属性处load一个贴图。最终运行的结果如图:
场景中的节点树:
保存当前场景为pong.scn并将当前场景在Scene-->Project Settings处设置为main scene。
对于视频游戏的输入方式有许多,键盘,鼠标,手柄,多点触屏等等,然而这个游戏是乒乓游戏,只需要输入上下来控制球拍就可以了,处理所有可能的输入方法是很令人沮丧的并且需要很多的代码,大多数游戏允许控制器的自定制使这种情况更加糟糕,对于这点,godot自建了"Input Actions",定义一个输入动作,然后输入动作被触发时输入方法就会添加到输入动作中。
再一次打开Scene-->Project Settings,这次点开"Input Map"选项卡。添加4个actions: "left_move_up","left_move_down","right_move_up","right_move_down",并为这4个动作指定按键。如图所示:
为场景中的root节点添加一个脚本,编辑脚本,脚本会继承Node2D,
extends Node2D
func _ready():
pass
在构造函数中,要做2件事情,第一件事情启动processing,第二件事情是保存有用的变量,比如场景和球拍的尺寸:
extends Node2D var screen_size var pad_size func _ready(): screen_size = get_viewport_rect().size pad_size = get_node("left").get_texture().get_size() set_process(true)接下来,添加一些在游戏中会用到的变量:
#speed of the ball (in pixels/second0 var ball_speed = 80 #direction of the ball (normal vector) var direction = Vector2(-1,0) #constant for pad speed (also in pixels/second) const PAD_SPEED = 150最后,是process函数:
func _process(delta):获得一些对接下来的运算有用的值,第一个是球的位置(也就是球节点的x,y坐标),第二个是矩形球拍的位置,中间的分界线的位置,
var ball_pos = get_node("ball").get_pos() var left_rect = Rect2( get_node("left").get_pos() - pad_size/2, pad_size ) var right_rect = Rect2( get_node("right").get_pos() - pad_size/2, pad_size )球是运动的,所以球的位置进行如下计算:
ball_pos+=direction*ball_speed*delta接下来,假设球在一个新位置,应该对球和周围的物体之间进行碰撞检测,首先是场景底部和顶部:
if ( (ball_pos.y<0 and direction.y <0) or (ball_pos.y>screen_size.y and direction.y>0)): direction.y = -direction.y如果与其中一个球拍发生了碰撞,球应该向相反方向运动,并且运动的速度也要增加一点点:
if ( (left_rect.has_point(ball_pos) and direction.x < 0) or (right_rect.has_point(ball_pos) and direction.x > 0)): direction.x=-direction.x ball_speed*=1.1 direction.y=randf()*2.0-1 direction = direction.normalized()
如果球出了屏幕,则game over,重新开始游戏:
if (ball_pos.x<0 or ball_pos.x>screen_size.x): ball_pos=screen_size*0.5 #ball goes to screen center ball_speed=80 direction=Vector2(-1,0)关于球的设置基本完成,接下来要不断更新球的位置:
get_node("ball").set_pos(ball_pos)
接下来是球拍的设置,只需要根据玩家的输入来确定球拍的运动方向,接下来的是输入类:
#move left pad var left_pos = get_node("left").get_pos() if (left_pos.y > 0 and Input.is_action_pressed("left_move_up")): left_pos.y+=-PAD_SPEED*delta if (left_pos.y < screen_size.y and Input.is_action_pressed("left_move_down")): left_pos.y+=PAD_SPEED*delta get_node("left").set_pos(left_pos) #move right pad var right_pos = get_node("right").get_pos() if (right_pos.y > 0 and Input.is_action_pressed("right_move_up")): right_pos.y+=-PAD_SPEED*delta if (right_pos.y < screen_size.y and Input.is_action_pressed("right_move_down")): right_pos.y+=PAD_SPEED*delta get_node("right").set_pos(right_pos)
好了,乒乓的游戏demo就完成了!
最终的整个游戏的代码:
extends Node2D
var screen_size
var pad_size
var ball_speed=80
var direction=Vector2(-1,0)
const PAD_SPEED=150
func _ready():
screen_size=get_viewport_rect().size
pad_size=get_node("left").get_texture().get_size()
set_process(true)
func _process(delta):
var ball_pos = get_node("ball").get_pos()
var left_rect = Rect2( get_node("left").get_pos() - pad_size/2, pad_size )
var right_rect = Rect2( get_node("right").get_pos() - pad_size/2, pad_size )
ball_pos+=direction*ball_speed*delta
if ( (ball_pos.y<0 and direction.y <0) or (ball_pos.y>screen_size.y and direction.y>0)):
direction.y = -direction.y
if ( (left_rect.has_point(ball_pos) and direction.x < 0) or (right_rect.has_point(ball_pos) and direction.x > 0)):
direction.x=-direction.x
ball_speed*=1.1
direction.y=randf()*2.0-1
direction = direction.normalized()
if (ball_pos.x<0 or ball_pos.x>screen_size.x):
ball_pos=screen_size*0.5 #ball goes to screen center
ball_speed=80
direction=Vector2(-1,0)
get_node("ball").set_pos(ball_pos)
#move left pad
var left_pos = get_node("left").get_pos()
if (left_pos.y > 0 and Input.is_action_pressed("left_move_up")):
left_pos.y+=-PAD_SPEED*delta
if (left_pos.y < screen_size.y and Input.is_action_pressed("left_move_down")):
left_pos.y+=PAD_SPEED*delta
get_node("left").set_pos(left_pos)
#move right pad
var right_pos = get_node("right").get_pos()
if (right_pos.y > 0 and Input.is_action_pressed("right_move_up")):
right_pos.y+=-PAD_SPEED*delta
if (right_pos.y < screen_size.y and Input.is_action_pressed("right_move_down")):
right_pos.y+=PAD_SPEED*delta
get_node("right").set_pos(right_pos)