交互媒体技术应用——2D横版冒险游戏初尝试

2023-11-21 20:20

本文主要是介绍交互媒体技术应用——2D横版冒险游戏初尝试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

2D横版冒险游戏——模拟人生《Just Die》

  • 想法
  • 背景
    • 使用工具
    • 参考资料
  • 关键技术
    • 小球的运动
    • 碰撞检测
    • 粒子系统
    • 优化算法
      • 粒子系统的预处理
      • 从预处理的粒子系统中获取需要的子系统
    • 其他
  • 后记
  • 附录

想法

最早是在B站看到一个视频,介绍了一个模拟人生的横版游戏,玩家需要操控游戏中的角色,根据不同的关卡做出不同的举动,来完成他的一生。简单但是很有深意,让我思考了很久,并在心里埋下了这个想法。这是一个就我个人而言代入感十分强烈的小Demo,包含我对这20年成长的一些思考,可能不有趣,而且由于代码能力不足,有一些糟糕的bug,导致游戏可玩性不强,以后应该会继续做,做出我满意的样子来。

背景

使用工具

processing

参考资料

《代码本色 The Nature of Code》 —— Daniel Shiffman
在这里插入图片描述
本Demo中参考的内容主要包含本书的前四章,向量、力、粒子系统等。

关键技术

小球的运动

将小球定义为包含位置(location)、速度(velocity)以及加速度(acceleration)的对象,根据加速度更新速度,根据速度更新位置,来实现小球的运动效果。这三个变量都存储在Processing自带的向量PVector中。

class people extends Collider {PVector velocity;  //速度PVector acceleration;  //加速度float topspeed=2; //最大速度float mass=10;  //质量float c=0.001;//摩擦力系数people() {location=new PVector(10, height-10);velocity=new PVector(0, 0);acceleration=new PVector(0, 0);R=5.0;}people(PVector location_, PVector velocity_, PVector acceleration_, float R_) {location=location_.get();velocity=velocity_.get();acceleration=acceleration_.get();R=R_;}}

在Update中更新变量,并在display绘制实时图像:

  void update() {applygravity();velocity.add(acceleration);location.add(velocity);velocity.limit(topspeed);acceleration=new PVector(0, 0);}void display() {fill(0);ellipse(location.x, location.y, 2*R, 2*R);}

这里面还包含了对力的应用addforce();我们知道,速度决定位置的变化,加速度决定速度的变化,而加速度来源于力,因此当我们想要改变一个物体的运动状态时,只需要给他加上一个力即可:

  void applyForce(PVector force) {PVector f=force.get();f.div(mass);acceleration.add(f);}

还可以细分为许多不同类型的力,如重力、摩擦力、弹力、万有引力等:

  void applyfriction() {PVector velocity_=velocity;velocity_.mult(-1);velocity_.normalize();PVector friction=velocity_.mult(c);applyForce(friction);}
  void applygravity() {PVector gravity=new PVector(0, 0.2);applyForce(gravity);}

(本Demo中虽然有计算摩擦力的函数,但是由于一些不知名Bug以及时间有限没用实际应用摩擦力,这里只做展示)

碰撞检测

其实前人已经做了十分完善的、包含碰撞的物理库函数Box2D(该库在代码本色的第五章中有详细介绍),但是由于作业要求用到三章的知识,所以我没用调用物理库而是自己实现了一个简陋的碰撞检测机制:

  Collederflag isCollision(Collider p) {float Mindis=R+p.R;if (abs(location.x-p.location.x)<=Mindis&&abs(location.y-p.location.y)<=Mindis) {if (location.x>=p.location.x) {//左侧撞击flag.horiflag=-1;} else if (location.x<p.location.x) {//右侧撞击flag.horiflag=1;}if (location.y<=p.location.y) {//下侧撞击flag.verflag=1; //   println("上方");} else if (location.y>p.location.y) {//上侧撞击flag.verflag=-1;//  println("下方");}return flag;} else {return flag;}}

原理大概就是根据计算每个物体的中心间的距离,根据这个距离与半径之间的关系来判断物体是否发生碰撞。在该Demo中根据两个碰撞物体的不同还有多个类似的碰撞检测函数,这里就不放了(其实只是因为本人代码能力不足,导致代码有些乱,也没用运用接口)。

粒子系统

在这里插入图片描述
在本Demo中存在各种不同的对象,我们将他们存储在粒子系统中。比如图片中作为边界和障碍物的砖块:
我们将他们定义为rectframe类,并在ArrayLIst frames中存储他们:

class rectframe extends frame {rectframe(PVector location_, float R_) {location=location_.get();R=R_;}void display() {rectMode(CENTER); stroke(255);strokeWeight(1);fill(0);rect(location.x, location.y, 2*R, 2*R);}
}
ArrayList<frame> frames = new ArrayList<frame>();

类似的还有图中的发射装置、发射出的子弹等,都是存储在粒子系统中的,以便于我们对一类对象进行相同的操作。

ArrayList<shootframe> shootframes = new ArrayList<shootframe>();
ArrayList<record> records = new ArrayList<record>();
ArrayList <moveblock> moveblocks=new ArrayList<moveblock>();

遍历粒子系统中的所有对象并在画面上绘制:

      for (frame f : frames) {f.display();}

优化算法

为了给小球施加力,我们需要判断小球是否与其他物体发生了碰撞,但是如果每帧都让小球对所有物体进行一次碰撞检测,这显然是不现实并且十分浪费的。所以我们需要进行一些优化,首先我们对所有数据预处理。

粒子系统的预处理

我们知道粒子系统就像一个能存储结构体的数组。而将数据存入粒子系统也很简单:

    List.add(f);

其中List 是ArrayList类型的对象,而f就是你要存储的数据。
但是只是存储是不够的,为了减少计算量,在每次存储新元素时,我们按照位置来插入元素,这里运用了之前在数据结构还是哪门课上学习的思路。这就好比现在给你一个乱序的数组[1,8,2,5,3,6,0,2],让你找一个大于3小于6的数,那么我们必须对每个元素进行判断,其是否大于3?其是否小于6?而如果给你一个排好序的数组[0,1,2,2,3,5,6,8],那么我们只需要从头开始判断,当我们找到数组中第一个大于3的数的位置,再从这个位置开始,找到第一个大于6的数的位置,这两个位置之间的数,就是我们需要的。但是每帧都对所有粒子系统排序显然效率也是很低的,所以我们只在生成对象,插入粒子系统的过程中,按照其x的坐标插入,就可以插入得到一个有序的粒子系统:

//---------------用于将新生成的frame对象插入ArrayList中
void insert(ArrayList List, frame f, int min, int max) {if (max==0) {//初始化List.add(f);return;}int mid=(max+min)/2;frame p=(frame)List.get(mid);//println(p.location.x);//println("mid:"+mid);//println("min:"+min);//println("max:"+max);frame pmin=(frame)List.get(min);frame pmax=(frame)List.get(max-1);//println("pmin:"+pmin.location.x);//println("pmax:"+pmax.location.x);if (f.location.x<pmin.location.x) {List.add(0, f);return;} else if (f.location.x>pmax.location.x) {List.add(max, f);return;} else if (f.location.x<=p.location.x) {frame pmid=(frame)List.get(mid-1);if (f.location.x>=pmid.location.x) {List.add(mid, f);return;}max=mid;insert(List, f, min, max);} else if (f.location.x>=p.location.x) {frame pmid=(frame)List.get(mid+1);if (f.location.x<=pmid.location.x) {List.add(mid+1, f);return;}min=mid;insert(List, f, min, max);}
}

从预处理的粒子系统中获取需要的子系统

然后当我们需要进行碰撞检测时,我们只需要根据阈值,从粒子系统中取出可能进行碰撞的子系统,对子系统中的粒子进行碰撞检测即可:

// 遍历数组,只取出ArrayList中有可能与YOU进行碰撞的对象进行碰撞检测
ArrayList<frame> findArrayList(ArrayList<frame> frames, Collider p) {ArrayList<frame> newframes=new ArrayList<frame>();float x=p.location.x;float R=p.R;float Up=x+maxR+R;float Down=x-maxR-R;//println("x:"+x);//  println("Up:"+Up);//    println("Down:"+Down);for (frame f : frames) {if (f.location.x>=Down&&f.location.x<=Up) {newframes.add(f);}}return newframes;
}

其他

其他还包括许多诸如开始界面的绘制、死亡提示、电影谢幕效果等,这里不放太多代码,具体直接看Demo就好:

void Gameover() {fill(0);rect(width/2, height/2, 3*width/4, height*3/4);textAlign(CENTER);fill(255);textSize(45);text("You Die", width/2, height/2);textSize(20);text("left click to continue", width/2, height/2+100);text("right click to reset", width/2, height/2+150);
}

后记

其实个人对这个Demo不是很满意,太过简陋的碰撞检测,以及还有许多想法都没有实现,对Processing和Java本身也不是很擅长,代码基础不足。以后应该会继续完善这个想法,附录放上完整的代码、可执行文件和《代码本色》PDF版。

附录

《代码本色 The Nature of Code》:链接:https://pan.baidu.com/s/1nxk5u4oIBDiEuUsOFi9Syw 密码:h0sv
《Just Die》可执行文件:链接:https://pan.baidu.com/s/1WXzLKgeGWmTb8dZENuoSBA 密码:kutl
《Just Die》源文件:链接:https://pan.baidu.com/s/1AtQ9K9eBw393o-9kyJHgoA 密码:lp6v

这篇关于交互媒体技术应用——2D横版冒险游戏初尝试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/404870

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

zoj3820(树的直径的应用)

题意:在一颗树上找两个点,使得所有点到选择与其更近的一个点的距离的最大值最小。 思路:如果是选择一个点的话,那么点就是直径的中点。现在考虑两个点的情况,先求树的直径,再把直径最中间的边去掉,再求剩下的两个子树中直径的中点。 代码如下: #include <stdio.h>#include <string.h>#include <algorithm>#include <map>#

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

AI行业应用(不定期更新)

ChatPDF 可以让你上传一个 PDF 文件,然后针对这个 PDF 进行小结和提问。你可以把各种各样你要研究的分析报告交给它,快速获取到想要知道的信息。https://www.chatpdf.com/

金融业开源技术 术语

金融业开源技术  术语 1  范围 本文件界定了金融业开源技术的常用术语。 本文件适用于金融业中涉及开源技术的相关标准及规范性文件制定和信息沟通等活动。

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。