游戏中物体比较多,这里源码里用了两个类封装了游戏中物体的主要属性,方便游戏中物体的封装。
1.GameObject类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package
com.zhf.mylibgdx;
import
com.badlogic.gdx.math.Rectangle;
import
com.badlogic.gdx.math.Vector2;
/**
* 所有的游戏物体都会在一个平面内绘制(或者说在屏幕大小内绘制),那么所有的物体都应该包含一个位置(position) 和一个作用范围(bounds)
* @author ZHF
*
*/
public
class
GameObject {
public
final
Vector2 position;
//位置
public
final
Rectangle bounds;
//作用范围
/**postion在这里是指游戏物体的中心点,而bounds中的x ,y 坐标是指这个游戏原素在屏幕坐标系中的作用起点,也就是矩形的左下角顶点**/
public
GameObject(
float
x,
float
y,
float
width,
float
height) {
this
.position =
new
Vector2(x, y);
this
.bounds =
new
Rectangle(x - width /
2
, y - height /
2
, width, height);
}
}
|
2.DynamicGameObject类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package
com.zhf.mylibgdx;
import
com.badlogic.gdx.math.Vector2;
/**
* 会移动的游戏物体
* @author ZHF
*
*/
public
class
DynamicGameObject
extends
GameObject {
//包含了 x, y 轴方向相关的运动信息。
public
final
Vector2 velocity;
//速度
public
final
Vector2 accel;
//加速度
public
DynamicGameObject (
float
x,
float
y,
float
width,
float
height) {
super
(x, y, width, height);
velocity =
new
Vector2();
accel =
new
Vector2();
}
}
|
接下来就是让游戏中的物体来分别根据自己的情况去继承它们:
Bob ------> 主角
Castle -----> 城堡
Coin -----> 金币
Platform ------> 平台
Spring -------> 弹簧
Squirrel -------> 空中飞行的松鼠
这里我们先将这六个类写出来,待会实现一下跳板是如何显示出来,我们就大体知道了整个游戏的逻辑了。ok! 上代码!
1.Bob类:
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
|
package
com.zhf.mylibgdx;
/**
* 主角
* @author ZHF
*
*/
public
class
Bob
extends
DynamicGameObject {
//主角状态
public
static
final
int
BOB_STATE_JUMP =
0
;
//跳跃
public
static
final
int
BOB_STATE_FALL =
1
;
//下落
public
static
final
int
BOB_STATE_HIT =
2
;
//碰撞
//速度
public
static
final
float
BOB_JUMP_VELOCITY =
11
;
//跳跃的速度
public
static
final
float
BOB_MOVE_VELOCITY =
20
;
//移动的速度
//宽和高
public
static
final
float
BOB_WIDTH =
0
.8f;
public
static
final
float
BOB_HEIGHT =
0
.8f;
int
state;
//状态
float
stateTime;
//状态持时间
public
Bob(
float
x,
float
y) {
super
(x, y, BOB_WIDTH, BOB_HEIGHT);
//初始化状态
state = BOB_STATE_FALL;
stateTime =
0
;
}
/**刷新**/
public
void
update (
float
deltaTime) {
//x,y轴速度的大小
velocity.add(World.gravity.x * deltaTime, World.gravity.y * deltaTime);
//主角当前移动的位置
position.add(velocity.x * deltaTime, velocity.y * deltaTime);
bounds.x = position.x - bounds.width /
2
;
bounds.y = position.y - bounds.height /
2
;
//跳跃状态
if
(velocity.y >
0
&& state != BOB_STATE_HIT) {
if
(state != BOB_STATE_JUMP) {
state = BOB_STATE_JUMP;
stateTime =
0
;
}
}
//下落状态
if
(velocity.y <
0
&& state != BOB_STATE_HIT) {
if
(state != BOB_STATE_FALL) {
state = BOB_STATE_FALL;
stateTime =
0
;
}
}
//边界限制
if
(position.x <
0
) position.x = World.WORLD_WIDTH;
if
(position.x > World.WORLD_WIDTH) position.x =
0
;
//状态持续时间
stateTime += deltaTime;
}
/**撞到松鼠**/
public
void
hitSquirrel () {
velocity.set(
0
,
0
);
state = BOB_STATE_HIT;
stateTime =
0
;
}
/**撞到跳板**/
public
void
hitPlatform () {
velocity.y = BOB_JUMP_VELOCITY;
state = BOB_STATE_JUMP;
stateTime =
0
;
}
/**撞到弹簧**/
public
void
hitSpring () {
velocity.y = BOB_JUMP_VELOCITY *
1
.5f;
state = BOB_STATE_JUMP;
stateTime =
0
;
}
}
|
2.Castle类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package
com.zhf.mylibgdx;
/**
* 城堡
* @author ZHF
*
*/
public
class
Castle
extends
GameObject {
//宽和高
public
static
float
CASTLE_WIDTH =
1
.7f;
public
static
float
CASTLE_HEIGHT =
1
.7f;
public
Castle(
float
x,
float
y) {
super
(x, y, CASTLE_WIDTH, CASTLE_HEIGHT);
}
}
|
3.Coin类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package
com.zhf.mylibgdx;
/**
* 金币
* @author ZHF
*
*/
public
class
Coin
extends
GameObject {
// 宽和高
public
static
final
float
COIN_WIDTH =
0
.5f;
public
static
final
float
COIN_HEIGHT =
0
.8f;
// 金币的分值
public
static
final
int
COIN_SCORE =
10
;
float
stateTime;
// 状态持续时间
public
Coin(
float
x,
float
y) {
super
(x, y, COIN_WIDTH, COIN_HEIGHT);
stateTime =
0
;
}
/**刷新**/
public
void
update(
float
deltaTime) {
stateTime += deltaTime;
}
}
|
4.Platform类:
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
|
package
com.zhf.mylibgdx;
/**
* 跳板
* @author ZHF
*
*/
public
class
Platform
extends
DynamicGameObject {
//宽和高
public
static
final
float PLATFORM_WIDTH =
2
;
public
static
final
float PLATFORM_HEIGHT =
0
.5f;
//跳板的类型
public
static
final
int
PLATFORM_TYPE_STATIC =
0
;
//静止
public
static
final
int
PLATFORM_TYPE_MOVING =
1
;
//运动
//跳板的状态
public
static
final
int
PLATFORM_STATE_NORMAL =
0
;
//正常
public
static
final
int
PLATFORM_STATE_PULVERIZING =
1
;
//破碎
public
static
final
float PLATFORM_PULVERIZE_TIME =
0
.2f *
4
;
//破碎所需时间
public
static
final
float PLATFORM_VELOCITY =
2
;
//跳板移动速度
int
type;
//类型 :静止、移动
int
state;
//状态:正常、破碎
float stateTime;
//状态持续时间
public
Platform (
int
type, float x, float y) {
super
(x, y, PLATFORM_WIDTH, PLATFORM_HEIGHT);
this
.type = type;
this
.state = PLATFORM_STATE_NORMAL;
//正常状态
this
.stateTime =
0
;
//若为移动类型,赋值移动速度
if
(type == PLATFORM_TYPE_MOVING) {
velocity.x = PLATFORM_VELOCITY;
}
}
/**刷新**/
public
void
update (float deltaTime) {
//移动跳板
if
(type == PLATFORM_TYPE_MOVING) {
//跳板移动位置
position.add(velocity.x * deltaTime,
0
);
bounds.x = position.x - PLATFORM_WIDTH /
2
;
bounds.y = position.y - PLATFORM_HEIGHT /
2
;
//左边界限制
if
(position.x < PLATFORM_WIDTH /
2
) {
velocity.x = -velocity.x;
position.x = PLATFORM_WIDTH /
2
;
}
//右边界限制
if
(position.x > World.WORLD_WIDTH - PLATFORM_WIDTH /
2
) {
velocity.x = -velocity.x;
position.x = World.WORLD_WIDTH - PLATFORM_WIDTH /
2
;
}
}
//状态持续时间
stateTime += deltaTime;
}
/**破碎**/
public
void
pulverize () {
state = PLATFORM_STATE_PULVERIZING;
stateTime =
0
;
velocity.x =
0
;
}
}
|
5.Spring类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package
com.zhf.mylibgdx;
/**
* 弹簧
* @author ZHF
*
*/
public
class
Spring
extends
GameObject {
//宽和高
public
static
float
SPRING_WIDTH =
0
.3f;
public
static
float
SPRING_HEIGHT =
0
.3f;
public
Spring(
float
x,
float
y) {
super
(x, y, SPRING_WIDTH, SPRING_HEIGHT);
}
}
|
6.Squirrel类:
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
|
package
com.zhf.mylibgdx;
/**
* 松鼠
* @author ZHF
*
*/
public
class
Squirrel
extends
DynamicGameObject {
//宽和高
public
static
final
float
SQUIRREL_WIDTH =
1
;
public
static
final
float
SQUIRREL_HEIGHT =
0
.6f;
//速度
public
static
final
float
SQUIRREL_VELOCITY = 3f;
float
stateTime =
0
;
//状态持续时间
public
Squirrel (
float
x,
float
y) {
super
(x, y, SQUIRREL_WIDTH, SQUIRREL_HEIGHT);
//为松鼠x轴方向赋值
velocity.set(SQUIRREL_VELOCITY,
0
);
}
/**刷新**/
public
void
update (
float
deltaTime) {
//松鼠移动位置
position.add(velocity.x * deltaTime, velocity.y * deltaTime);
bounds.x = position.x - SQUIRREL_WIDTH /
2
;
bounds.y = position.y - SQUIRREL_HEIGHT /
2
;
//左边界限制
if
(position.x < SQUIRREL_WIDTH /
2
) {
position.x = SQUIRREL_WIDTH /
2
;
velocity.x = SQUIRREL_VELOCITY;
}
//右边界限制
if
(position.x > World.WORLD_WIDTH - SQUIRREL_WIDTH /
2
) {
position.x = World.WORLD_WIDTH - SQUIRREL_WIDTH /
2
;
velocity.x = -SQUIRREL_VELOCITY;
}
//状态持续时间
stateTime += deltaTime;
}
}
|
以上就是游戏中六个物体类的代码,都十分的相似,代码里都注释了,这里不再一一讲解,可能有些变量没有完全写出,大家还是以源码为主,接下来我们要干的工作就是如何在游戏界面里显示出跳板?
首先,在World类中:
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
|
package
com.zhf.mylibgdx;
import
java.util.ArrayList;
import
java.util.List;
import
java.util.Random;
import
com.badlogic.gdx.math.Vector2;
/**
* 统一管理世界中各个部分
* @author ZHF
*
*/
public
class
World {
/**世界监听器接口**/
public
interface
WorldListener {
//跳跃
public
void
jump ();
//高跳
public
void
highJump ();
//碰撞
public
void
hit ();
//收集金币
public
void
coin ();
}
//宽和高
public
static
final
float
WORLD_WIDTH =
10
;
public
static
final
float
WORLD_HEIGHT =
15
*
20
;
//状态
public
static
final
int
WORLD_STATE_RUNNING =
0
;
//运行
public
static
final
int
WORLD_STATE_NEXT_LEVEL =
1
;
//下一关
public
static
final
int
WORLD_STATE_GAME_OVER =
2
;
//游戏结束
//世界监听器
public
WorldListener listener;
//重力
public
static
final
Vector2 gravity =
new
Vector2(
0
, -
12
);
//随机数
public
Random rand;
//游戏中物体
public
final
List<Platform> platforms;
//跳板
public
World(WorldListener listener) {
this
.listener = listener;
this
.platforms =
new
ArrayList<Platform>();
rand =
new
Random();
generateLevel();
}
/**生成关卡中除了Bob外所有的物体**/
private
void
generateLevel() {
float
y = Platform.PLATFORM_HEIGHT /
2
;
float
maxJumpHeight = Bob.BOB_JUMP_VELOCITY * Bob.BOB_JUMP_VELOCITY / (
2
* -gravity.y);
while
(y < WORLD_HEIGHT - WORLD_WIDTH /
2
) {
int
type = rand.nextFloat() >
0
.8f ? Platform.PLATFORM_TYPE_MOVING : Platform.PLATFORM_TYPE_STATIC;
float
x = rand.nextFloat() * (WORLD_WIDTH - Platform.PLATFORM_WIDTH) + Platform.PLATFORM_WIDTH /
2
;
Platform platform =
new
Platform(type, x, y);
platforms.add(platform);
y += (maxJumpHeight -
0
.5f);
y -= rand.nextFloat() * (maxJumpHeight /
3
);
}
}
/**刷新界面**/
public
void
update(
float
deltaTime,
float
accelX) {
updatePlatforms(deltaTime);
}
/**刷新跳板**/
private
void
updatePlatforms(
float
deltaTime) {
int
len = platforms.size();
for
(
int
i =
0
; i < len; i++) {
Platform platform = platforms.get(i);
//取出集合中的跳板对象,调用其自身的刷新方法
platform.update(deltaTime);
//若状态为破碎状态,将该跳板对象移除出去
if
(platform.state == Platform.PLATFORM_STATE_PULVERIZING && platform.stateTime > Platform.PLATFORM_PULVERIZE_TIME) {
platforms.remove(platform);
len = platforms.size();
}
}
}
}
|
分析:这里我们还是在上一讲的代码的基础上,增加了platform对象及其实例化,还有与其相关的刷新方法。最重要的是在World的构造方法中,初始化跳板集合,并且调用了 generateLevel()方法来生成关卡中除了Bob外所有的物体。
游戏中物体的创建主要是围绕Platform来生成的。在While循环内,通过不断增加y坐标的值,使用随机数rand 和 物体的内置属性来生成不同的游戏物体。比如,对于Playform 有移动和不移动两种,同时它内置的宽度为2(每单位为32个像素),高度为0.5,结合rand就能达到随机生成Playform的效果。
其次就是WorldRenderer类:
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
|
package
com.zhf.mylibgdx;
import
com.badlogic.gdx.graphics.OrthographicCamera;
import
com.badlogic.gdx.graphics.g2d.SpriteBatch;
import
com.badlogic.gdx.graphics.g2d.TextureRegion;
/**
* 用来把每个对象关联相应的图片资源,同时控制相机,实现动画。
* @author ZHF
*
*/
public
class
WorldRenderer {
//宽和高
static
final
float
FRUSTUM_WIDTH =
10
;
static
final
float
FRUSTUM_HEIGHT =
15
;
World world;
//世界
OrthographicCamera cam;
//相机
SpriteBatch batch;
//用于绘画
TextureRegion background;
//背景图片
public
WorldRenderer(SpriteBatch batch, World world) {
this
.world = world;
//OrthographicCamera 被定义成 宽度为10,高度为15,同样的也把相机对准中心点。
this
.cam =
new
OrthographicCamera(FRUSTUM_WIDTH, FRUSTUM_HEIGHT);
//它指定了和屏幕一样大小的 OrthographicCamera ,并把相机对准屏幕的中心。
this
.cam.position.set(FRUSTUM_WIDTH /
2
, FRUSTUM_HEIGHT /
2
,
0
);
this
.batch = batch;
}
/**渲染**/
public
void
render () {
cam.update();
//它的作用都是通过把映射矩阵绑定给SpritBatch,告诉SpritBatch怎么去绘制图形
batch.setProjectionMatrix(cam.combined);
//渲染背景
renderBackground();
//渲染游戏中各种元素(Bob,跳板,松鼠,弹簧。。)下一讲中会具体讲到
renderObjects();
}
/**渲染游戏中各种物体(Bob,跳板,松鼠,弹簧,城堡,金币)**/
private
void
renderObjects() {
batch.enableBlending();
batch.begin();
//绘制跳板
renderPlatforms();
batch.end();
}
/**渲染背景**/
public
void
renderBackground () {
batch.disableBlending();
batch.begin();
batch.draw(Assets.backgroundRegion, cam.position.x - FRUSTUM_WIDTH /
2
, cam.position.y - FRUSTUM_HEIGHT /
2
, FRUSTUM_WIDTH,
FRUSTUM_HEIGHT);
batch.end();
}
/**渲染跳板**/
private
void
renderPlatforms () {
int
len = world.platforms.size();
for
(
int
i =
0
; i < len; i++) {
Platform platform = world.platforms.get(i);
TextureRegion keyFrame = Assets.platform;
// if (platform.state == Platform.PLATFORM_STATE_PULVERIZING) {
// keyFrame = Assets.brakingPlatform.getKeyFrame(platform.stateTime, Animation.ANIMATION_NONLOOPING);
// }
batch.draw(keyFrame, platform.position.x -
1
, platform.position.y -
0
.25f,
2
,
0
.5f);
}
}
}
|
分析:
1.在该类中,我们写了一个方法renderObjects()用于渲染游戏中各种物体(Bob,跳板,松鼠,弹簧,城堡,金币)
2.渲染跳板renderPlatforms ()方法里我们取出集合中的跳板对象,对应加载资源,并将其绘制出来。
最后,就是在Asset类中加载跳板资源
声明:
1
2
|
//游戏中各种物体
public
static
TextureRegion platform;
//跳板
|
实例化:
1
2
|
//游戏中各个物体
platform =
new
TextureRegion(items,
64
,
160
,
64
,
16
);
//跳板
|
运行一下,效果图:(每次运行起来跳板的位置都是随机的)
目前游戏还是没有主人公哦,在下一讲中,我们会加上主人公,同时显示出其他游戏物体,当然还有最重要的游戏碰撞检测,以及场景的移动。
源码下载:http://down.51cto.com/data/896982
本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1263869,如需转载请自行联系原作者