前言
- 这个只是练手的一个2D小游戏,不许商用哦
- 完成了原版的一个关卡的内容,跳板也只有一种,但是如果需要的话可以往深了做的
- 项目地址+Demo试玩(win64的exe在Client文件夹中)
1.贴图准备
- 使用到的工具是ps,切一个板,切一个主人公,再找一个背景墙,这样材料就准备齐全了~
跳板的逻辑
-
将跳板放入场景中后,因为涉及到了碰撞,因此给一个碰撞体组件
-
之后有个细节,就是如果任务触碰到板子的下方,是不会算作踩到跳板获得向上的速度的!这个需求可以从两方面来实现(一个就是当角色下落的时候才判断碰撞回调;二就是使用到下面这个Platform Effector 2D啦)注意需要在collider中的use by effector打钩
-
最后再给板子一个tag,用来判断碰撞,这样就可以将板子作为预制件,然后拖走啦 ~
人物的逻辑
- 首先人物会受到重力作用,因此加入Rigibody2D组件,并给其一个重力规模
- 需要计算碰撞,因此给一个碰撞体!记得把Is Trigger勾上,不√的话,我们用不了碰撞回调的OnTriggerEnter2D方法,因为角色会停在板子上,不会进入!
- 下面我们给角色一个控制的脚本
- 下面这个脚本的功能,有查看左右的越界(当左边越界的时候,角色会从右边出来,看起来左右地图不会出界,是联通的)
- 当角色触碰到板子上的时候会得到一个向上的速度
- 角色受到方向键的控制(细节:角色的朝向也会受到向左向右的影响)
public class Player : MonoBehaviour
{
public Rigidbody2D rb;
public float sensitive = 10f;
private void Update()
{
PlayerController();
//查看越界
checkOverEdge();
}
private void checkOverEdge()
{
if (transform.position.x < -6f)
{
transform.position = new Vector2(6f, transform.position.y);
}
if (transform.position.x > 6f)
{
transform.position = new Vector2(-6f, transform.position.y);
}
}
private void OnTriggerEnter2D(Collider2D col)
{
//下落的时候才计算碰撞。不然角色只要碰到东西就会往上飞
if (rb.velocity.y <= 0)
{
if (col.CompareTag("board"))
{
rb.velocity = new Vector2(0f, 10f);
}
}
if (col.CompareTag("win"))
{
SceneManager.LoadScene("Win");
}
}
private void PlayerController()
{
float horizontalAxis = 0;
horizontalAxis = Input.GetAxis("Horizontal");
if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow))
{
transform.rotation = Quaternion.Euler(new Vector3(0, 0, 0));
}
if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow))
{
transform.rotation = Quaternion.Euler(new Vector3(0, 180, 0));
}
rb.velocity = new Vector2(horizontalAxis * sensitive, rb.velocity.y);
}
相机的逻辑
- 相机的话就跟上一个小球跳圈的游戏是一样的道理,如果角色y大于相机y,那么相机跟着向上走
- 角色如果一下子跌落(与相机的y轴相差一定的大小,记作失败,重新加载游戏场景),游戏回到起点~
public class PlayerFollow : MonoBehaviour
{
public Transform PlayerTransform;
private Vector3 currentVelocity;
public Rigidbody2D playerRigidbody2D;
private void LateUpdate()
{
if (PlayerTransform.position.y >= transform.position.y)
{
Vector3 tmpv = new Vector3(transform.position.x, PlayerTransform.position.y, transform.position.z);
transform.position =
Vector3.SmoothDamp(transform.position, tmpv, ref currentVelocity, .3f * Time.deltaTime);
}
//掉入谷底,回到原点
if (PlayerTransform.position.y < transform.position.y - 3f)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
}
如何自动生成跳板
-
在场景中,专门有个空物体是用来自动生成板子的。就是个空物体,放在原点就好,方便地图生成。
-
这里生成地图的逻辑是在游戏开始的时候,在Start的时候就将本关卡所有的板子位置生成好了
-
在下面脚本中,按照一定的高度差,和一定的水平差随机生成numberOfPlatforms-1数量的板子,并在最后一次生成一个win point(在游戏中就是一面红旗,触碰到了算胜利!)
-
游戏中的板子水平距离不能太宽,不然跳不过去,因此这里写个while循环,如果生成过宽,则重新生成。
public class LevelGenerator : MonoBehaviour
{
public GameObject platformPrefab;
public int numberOfPlatforms;
public GameObject winPointPrefab;
public float levelWidth = 3f;
public float minY = .2f;
public float maxY = 1.8f;
private float lastx;
private void Start()
{
Vector3 spawnPosition = new Vector3();
for (int i = 0; i < numberOfPlatforms; i++)
{
spawnPosition.y += Random.Range(minY, maxY);
float tmpx = Random.Range(-levelWidth, levelWidth);
while (Math.Abs(tmpx - lastx) > 4f)
{
tmpx = Random.Range(-levelWidth, levelWidth);
}
lastx = tmpx;
spawnPosition.x = tmpx;
if (i == numberOfPlatforms - 1)
{
//生成win point
Instantiate(winPointPrefab, spawnPosition, Quaternion.identity);
}
else
{
Instantiate(platformPrefab, spawnPosition, Quaternion.identity);
}
}
}
}
如何赢得游戏
- 做一个标志物(这里用的是红旗),给其一个tag,作为预制体,被自动生成
- 当角色触碰到后,加载win场景~
- 这样好玩又解压的Demo就大功告成啦!具体可以查看工程代码~