使用Android完成案例教学

目录

题目:完成在Android平台下2个玩家分别利用2个手机连接在同一局域网下通过滑动摇杆分别使红飞机和黄飞机移动的开发。(全代码解析)


题目:完成在Android平台下2个玩家分别利用2个手机连接在同一局域网下通过滑动摇杆分别使红飞机和黄飞机移动的开发。(全代码解析)

用一个真机运行,连接此电脑 的模拟机进行利用2个手机连接在同一局域网下通过滑动摇杆分别使红飞机和黄飞机移动的开发

运行结果: 

模拟机:

真机:

DrawThread.java代码:
package com.example.client.thread;import com.example.clinet.view.GameView;import android.annotation.SuppressLint;
import android.graphics.Canvas;
import android.view.SurfaceHolder;public class DrawThread extends Thread
{private int SLEEP_SPAN =50;//睡眠的毫秒数private SurfaceHolder surfaceHolder;private GameView view;private boolean flag = true;public DrawThread(SurfaceHolder surfaceHolder, GameView view) {//构造器this.surfaceHolder = surfaceHolder;this.view = view;}public void setFlag(boolean flag) {//设置循环标记位this.flag = flag;}@SuppressLint("WrongCall")public void run(){Canvas c;while(flag){c = null;try{// 锁定整个画布,在内存要求比较高的情况下,建议参数不要为nullc = this.surfaceHolder.lockCanvas(null);synchronized (this.surfaceHolder){this.view.onDraw(c);}} finally{if (c != null){//更新屏幕显示内容this.surfaceHolder.unlockCanvasAndPost(c);}}try{Thread.sleep(SLEEP_SPAN);//睡眠指定毫秒数}catch(Exception e){e.printStackTrace();}}}
}

KeyThread.java代码:
package com.example.client.thread;import com.example.client.MainActivity;
import com.example.util.GameData;public class KeyThread extends Thread
{int SPAN_SLEEP=10;MainActivity father;boolean flag=true;public KeyThread(MainActivity father){this.father=father;}public void run(){while(flag){try{if(GameData.state==2){father.nt.dout.writeUTF("<#KEY#>"+father.KeyDispX+"|"+father.KeyDispY);}Thread.sleep(SPAN_SLEEP);}catch(Exception e){e.printStackTrace();}}}
}
更改自己电脑上的IP地址,win+R输入cmd,然后输入ipconfig命令获取此电脑的IP地址,NetworkThread.java代码如下:
package com.example.client.thread;import android.util.Log;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import com.example.client.MainActivity;
import com.example.util.GameData;public class NetworkThread extends Thread{MainActivity activity;Socket sc;DataInputStream din;DataOutputStream dout;public boolean flag=true;public NetworkThread(MainActivity activity){this.activity=activity;}public void run(){try{//与服务端建立连接 ,参数分别是要连接的服务端IP地址和要连接的服务端对应的监听端口Log.i("测试", "run: 开始连接");sc=new Socket("192.168.43.252",9999);din=new DataInputStream(sc.getInputStream());dout=new DataOutputStream(sc.getOutputStream());dout.writeUTF("<#CONNECT#>");Log.i("测试", "run: 完成连接");}catch(Exception e){Log.e("测试", "run: 执行失败",e );e.printStackTrace();return;}while(flag){try{String msg=din.readUTF();if(msg.startsWith("<#OK#>")){System.out.println("Connect ok...");GameData.state=1;}else if(msg.startsWith("<#BEGIN#>")){GameData.state=2;this.activity.kt.start();}else if(msg.startsWith("<#FULL#>")){System.out.println("Full...");break;}else if(msg.startsWith("<#GAME_DATA#>")){String nr=msg.substring(13);String[] strA=nr.split("\\|");int temprx=Integer.parseInt(strA[0]);int tempry=Integer.parseInt(strA[1]);int tempgx=Integer.parseInt(strA[2]);int tempgy=Integer.parseInt(strA[3]);synchronized(this.activity.gd.lock){this.activity.gd.rx=temprx;this.activity.gd.ry=tempry;this.activity.gd.gx=tempgx;this.activity.gd.gy=tempgy;}}}catch(Exception e){e.printStackTrace();}}try{din.close();dout.close();sc.close();}catch(Exception e){e.printStackTrace();}}
}

MainActivity.Java代码:
package com.example.client;import com.example.client.thread.KeyThread;
import com.example.client.thread.NetworkThread;
import com.example.clinet.view.GameView;
import com.example.util.GameData;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;public class MainActivity extends Activity {public int KeyDispX=0;//方向xpublic int KeyDispY=0;//方向ypublic Bitmap planer;public Bitmap planeg;public GameData gd=new GameData();public KeyThread kt=new KeyThread(this);public 	NetworkThread nt;GameView gv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);planer=BitmapFactory.decodeResource(getResources(), R.drawable.red);//红飞机planeg=BitmapFactory.decodeResource(getResources(), R.drawable.yellow);//黄飞机gv=(GameView)this.findViewById(R.id.mf1);}@Overridepublic boolean onCreateOptionsMenu(Menu menu){//调用Activity的getMenuInflater()得到一个MenuInflater,//使用inflate方法来把布局文件中的定义的菜单 加载给 第二个参数所对应的menu对象getMenuInflater().inflate(R.menu.activity_main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {if(item.getItemId()==R.id.menu_connect){if(this.nt==null){this.nt=new NetworkThread(MainActivity.this);this.nt.start();}}return true;}
}
ServerAgentThread.java代码如下:
package com.example.util;import java.io.*;
import java.net.*;
import java.util.*;public class ServerAgentThread extends Thread
{//�ͻ��˼�����static int count=0;//�ͻ����б�static List<ServerAgentThread> ulist=new ArrayList<ServerAgentThread>();//ȫ������static int rx=150;static int ry=750;static int gx=460;static int gy=750;//��������static Queue<Action> aq=new LinkedList<Action>();//����������static Object lock=new Object();Socket sc;DataInputStream din;DataOutputStream dout;int redOrYellow;boolean flag=true;public static void broadcastState(){for(ServerAgentThread sa:ulist){try{sa.dout.writeUTF("<#GAME_DATA#>"+rx+"|"+ry+"|"+gx+"|"+gy);}catch(Exception e){e.printStackTrace();}}}public ServerAgentThread(Socket sc){this.sc=sc;try{din=new DataInputStream(sc.getInputStream());dout=new DataOutputStream(sc.getOutputStream());}catch(Exception e){e.printStackTrace();}}public void run(){while(flag){try{String msg=din.readUTF();if(msg.startsWith("<#CONNECT#>")){if(count==0){dout.writeUTF("<#OK#>");redOrYellow=0;ulist.add(this);count++;System.out.println("==red connect...");
//						for(ServerAgentThread sa:ulist)
//						{
//							sa.dout.writeUTF("<#BEGIN#>");
//						}}else if(count==1){dout.writeUTF("<#OK#>");redOrYellow=1;ulist.add(this);count++;System.out.println("==yellow connect...");for(ServerAgentThread sa:ulist){sa.dout.writeUTF("<#BEGIN#>");}}else{dout.writeUTF("<#FULL#>");break;}}else if(msg.startsWith("<#KEY#>")){String iStr=msg.substring(7);String[] str=iStr.split("\\|");synchronized(lock){//���¶����������aq.offer(new Action(this.redOrYellow,Integer.parseInt(str[0]),Integer.parseInt(str[1])));}}}catch(Exception e){e.printStackTrace();}}try{din.close();dout.close();sc.close();}catch(Exception e){e.printStackTrace();}}
}
Joystick.java代码:
package com.example.util;import com.example.client.MainActivity;
import com.example.client.R;
import com.example.clinet.view.GameView;import static com.example.util.Constant.*;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;public class Joystick
{public MainActivity activity;public GameView view;public int length;public float x;public float y;public Joystick( GameView view,MainActivity activity,float x,float y){this.view=view;this.activity=activity;this.x=x;this.y=y;}public void drawJoystick(Canvas canvas){canvas.drawBitmap(BitmapFactory.decodeResource(this.activity.getResources(),R.drawable.yaogan1),JK_Start_x,JK_Start_y, null);canvas.drawBitmap(BitmapFactory.decodeResource(this.activity.getResources(),R.drawable.yaogan2),x,y,null);}public boolean change(float x,float y){length=getLength(this.view.pCenter.x,this.view.pCenter.y, x,y);if(length>radio){//如果手指触点不在大环范围内return false;}else if(length<radio){ //如果手指在摇杆活动范围内,则摇杆处于手指触摸位置this.view.mJoystick.x=x;this.view.mJoystick.y=y;}else{//设置摇杆位置,使其处于手指触摸方向的 摇杆活动范围边缘float angle=getRadian(this.view.pCenter.x,this.view.pCenter.y, x, y);this.view.mJoystick.x=(int)(this.view.pCenter.x+radio* Math.cos(angle));this.view.mJoystick.y=(int)(this.view.pCenter.y+radio*Math.sin(angle));}//方向this.activity.KeyDispX=(int) (x-this.view.pCenter.x);//x偏移量this.activity.KeyDispY=(int) (y-this.view.pCenter.y);//y偏移量return true;}
}

 Action.java代码:

package com.example.util;public class Action 
{int redOrYellow;//0-red 1-green	float keyX;float keyY;int span=20;//�ƶ�����public Action(int redOrYellow,float keyX,float keyY){this.redOrYellow=redOrYellow;this.keyX=keyX;this.keyY=keyY;}public void doAction(){		float xx=0;float yy=0;if(Math.sqrt(keyX*keyX+keyY*keyY)!=0){//ת��Ϊ��λ����ֵxx= (float) (keyX/Math.sqrt(keyX*keyX+keyY*keyY));yy=(float) (keyY/Math.sqrt(keyX*keyX+keyY*keyY));}if(redOrYellow==0){//��if(ServerAgentThread.ry+yy*span>=0&&ServerAgentThread.ry+yy*span<=1100){//���÷ɻ��ƶ���ΧServerAgentThread.ry+=yy*span;}			if(ServerAgentThread.rx+xx*span>=0&&ServerAgentThread.rx+xx*span<=600){ServerAgentThread.rx+=xx*span;}}else{//��if(ServerAgentThread.gy+yy*span>=0&&ServerAgentThread.gy+yy*span<=1100){//���÷ɻ��ƶ���ΧServerAgentThread.gy+=yy*span;}		if(ServerAgentThread.gx+xx*span>=0&&ServerAgentThread.gx+xx*span<=600){ServerAgentThread.gx+=xx*span;}}}
}
ActionThread.java代码:
package com.example.util;public class ActionThread extends Thread
{static final int SLEEP=5;boolean flag=true;public void run(){while(flag){Action a=null;synchronized(ServerAgentThread.lock){//��ȡ���Ƴ�����Ԫ��a=ServerAgentThread.aq.poll();}if(a!=null){a.doAction();ServerAgentThread.broadcastState();	}else{try{Thread.sleep(SLEEP);}catch(Exception e){e.printStackTrace();}}}}
}
Constant.java代码:
package com.example.util;public class Constant {public static final int radio=80;//半径public static final int JK_Start_x=30;//摇杆大环起点xpublic static final int JK_Start_y=830;//摇杆大环起点ypublic static final int  xJoystick=100;//摇杆小环xpublic static final int  yJoystick=900;//摇杆小环y//获取水平线夹角弧度public static float getRadian (float x1,float y1,float x2,float y2){float lenA=x2-x1;float lenB=y2-y1;float lenC=(float) Math.sqrt(lenA*lenA+lenB*lenB);float angle=(float)Math.acos(lenA/lenC);angle=angle*(y2<y1?-1:1);return angle;}//获取长度public static int getLength(float centerX,float centerY,float x,float y){int result=(int)Math.sqrt(Math.pow(x-centerX, 2)+Math.pow(y-centerY, 2));return result;}
}

GameData.java代码;
package com.example.util;public class GameData {public static int state=0;//0--未连接  1---成功连接  2--游戏开始public Object lock=new Object();public int rx=150;public int ry=750;public int gx=460;public int gy=750;
}
启动ServerThread.java代码:
package com.example.util;
import java.net.*;public class ServerThread extends Thread
{boolean flag=false;ServerSocket ss;public void run(){try{ss=new ServerSocket(9999);System.out.println("Server Listening on 9999...");flag=true;new ActionThread().start();}catch(Exception e){e.printStackTrace();}while(flag){try{Socket sc=ss.accept();System.out.println(sc.getInetAddress()+" connect...");new ServerAgentThread(sc).start();}catch(Exception e){e.printStackTrace();}}}public static void main(String args[]){new ServerThread().start();}
}

 main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><com.example.clinet.view.GameViewandroid:id="@+id/mf1"android:layout_width="fill_parent"android:layout_height="wrap_content"/></LinearLayout>

 今天就分享到这里,感谢预览~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/807769.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MongoDB聚合运算符:$max

文章目录 语法使用空值和缺失值的处理数组操作数的处理 举例在$group阶段使用在$setWindowFields阶段使用在$project阶段使用 $max聚合运算符用于返回最大值。 $max对于不同的类型的值使用BSON的比较顺序。 $max可以用于下面的这些阶段&#xff1a; $addFields$bucket$bucket…

解决unbuntu更新到23.10 mantic firefox无法使用的问题

产看历史版本号&#xff1a; 升级到最新版本后查看&#xff1a; roottesthost01:/home/test/Desktop# lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 23.10 Release: 23.10 Codename: mantic 打开firefox发现图标找…

【教程】四种方法将App打包为IPA文件类型

摘要 本教程总结了将App应用程序打包为IPA包的四种常用方法&#xff0c;包括Apple推荐的方式、iTunes拖入方法、自动编译脚本和解压改后缀名方法。每种方法都有其特点和适用场景&#xff0c;在实际开发中可以根据需求选择合适的方式进行打包。通过本教程&#xff0c;您将了解到…

mapper.xml特殊SQL语句汇总(持续更新中)

1.通用查询结果列 <sql id"Base_Column_List">user_id, user_name, user_password </sql>用法&#xff1a; <select id"selectUser" resultType"com.example.YourUser">SELECT<include refid"Base_Column_List"…

HTML2:列表和表格

列表 有序列表 ordered list ol 无序列表 unordered list ul 定义列表 definition list dl 1,有序列表 每条列表前自带一个序号 2,无序列表 每条列表前自带一个小圆点 3,定义列表 注意:dl中放的不是li列表而是dt列表和dd表项 dt代表术语标题 dd代表术语内容 一个…

服务器出现404错误怎么处理

很多站长使用虚拟主机或者云服务器做网站的以为这个就是空间商的问题&#xff0c;空间商主要服务虚拟主机的运维&#xff0c;跟404出现错误 并不完全直接关联的&#xff0c; 也是关于多方面的问题存在的&#xff0c; 现在由壹基比小鑫来给大家讲解下&#xff1a; 1.错误原因 HT…

从零开始学Spring Boot系列-集成MyBatis-Plus

在Spring Boot应用开发中&#xff0c;MyBatis-Plus是一个强大且易于使用的MyBatis增强工具&#xff0c;它提供了很多实用的功能&#xff0c;如代码生成器、条件构造器、分页插件等&#xff0c;极大地简化了MyBatis的使用和配置。本篇文章将指导大家如何在Spring Boot项目中集成…

【C语言】函数递归编程题

目录 题目一&#xff1a; 题目二&#xff1a; 题目三&#xff1a; 题目四&#xff1a; 总结 题目一&#xff1a; 题目&#xff1a;接受一个整型值&#xff08;无符号&#xff09;&#xff0c;按照顺序打印它的每一位。&#xff08;递归完成&#xff09; 列如&#xff1a; …

2024.3.30力扣每日一题——需要添加的硬币的最小数量

2024.3.30 题目来源我的题解方法一 数学贪心 题目来源 力扣每日一题&#xff1b;题序&#xff1a;2952 我的题解 方法一 数学贪心 首先将数组 coins按升序排序&#xff0c;然后计算需要添加的硬币的最小数量。 关键&#xff1a;对于正整数 x&#xff0c;如果区间 [1,x−1] 内…

Vue3入门大全(持续更新)

什么是Vue3 Vue.js 是一款流行的 JavaScript 前端框架&#xff0c;用于构建交互式的 Web 用户界面。Vue 3 是 Vue.js 的下一个主要版本&#xff0c;是对 Vue 2 的重大更新。Vue 3 在性能、开发体验和扩展性等方面都进行了改进和优化&#xff0c;其中一些重要的变化和功能包括&…

通过 CLI 和引入的方式使用 React:基础入门

使用React 有两种使用方式&#xff0c;主要有以下几个原因: 灵活性和适应性: 引入的方式可以让开发者在现有的 HTML 页面中快速引入 React,无需设置完整的项目环境。这适合小型或原型项目。 CLI 方式则更适合用于构建大型复杂的 React 应用程序,因为它提供了更完整的项目结构和…

探索 ChatGPT:解读 AI 对话的魔力(文末推荐一款AI工具聚合平台,可免费体验)

&#x1f947;作者简介&#xff1a;CSDN内容合伙人、新星计划第三季Python赛道Top1 &#x1f525;个人主页&#xff1a;hacker707的csdn博客 &#x1f4ac;推荐一款AI工具聚合平台&#x1f449;Hulu AI 探索 ChatGPT&#xff1a;解读 AI 对话的魔力 ChatGPT 的魅力如何使用 C…

JVM修炼之路【10】- 垃圾回收器和垃圾回收算法

垃圾回收算法 我们先简要看一下 四种主要的垃圾回收算法 看到这不禁感慨一下 人家1960年 都搞出GC算法了 太强了 评价标准 既然有这么多算法 那就跟各个牌子的游戏本一样 有个比较&#xff0c;这里我们重点介绍一下 垃圾回收算法的评价标准 这几个标准非常重要是 是后面理解很…

springCloudAlibaba集成sentinel实战(超详细)

一、Sentinel介绍 1. 什么是Sentinel Sentinel是阿里开源的项目&#xff0c;提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。 分布式系统的流量防卫兵&#xff1a; 随着微服务的普及&#xff0c;服务调用的稳定性变得越来越重要。Sentinel以“流…

你知道 Java 线程池的原理吗?

Java线程池是用于管理和复用线程的机制&#xff0c;它可以帮助开发者有效地管理线程的生命周期和资源&#xff0c;并提高应用程序的性能和稳定性。 1. 线程池概述 在计算机科学中&#xff0c;线程池是一种可用来执行异步任务的线程队列。它主要包含以下几个组成部分&#xff…

python连接mysql数据库并将dataframe的数据插入表中

代码中连接的sql表为"20230411_hangzhuanlie"&#xff0c;表结构如下&#xff1a; 代码如下&#xff08;按需修改用户名、库名等即可&#xff09;&#xff1a; import pymysql import pandas as pd from sqlalchemy import create_enginehost 127.0.0.1:3306/ user_…

科研学习|论文解读——基于旅游知识图谱的游客偏好挖掘和决策支持(IPM,2023)

原文题目 Mining tourist preferences and decision support via tourism-oriented knowledge graph 摘要 目前,旅游管理研究的重点是通过对异构用户生成的内容进行广泛分析,来理解旅游偏好的波动,制定有针对性的发展策略。然而,鉴于在线景点评论涉及过多的混合和无形维度…

【51单片机入门记录】IIC总线协议 EEPROM存储器AT24C02应用

目录 一、AT24C20相关函数操作流程 &#xff08;0&#xff09;根据第十五届蓝桥杯初始iic.c进行的初步修改&#xff08;便于编写后续函数&#xff09; &#xff08;1&#xff09;AT24C20存数据操作流程及代码 &#xff08;2&#xff09;AT24C02读数据操作流程及代码 &#…

一、OpenMIPS指令集CPU的ori指令的实现

前言 根据“自己动手写CPU”这本书学习&#xff0c;自己动手实现一个MIPS指令集的CPU。 本文章实现了一个ori指令即“或”操作的五级流水线&#xff0c;后续会持续添加其他指令完善此CPU。 文章作为学习笔记持续更新&#xff0c;源代码也在github上持续更新 项目源码https://…

MySQL 行锁和表锁是什么?区别,作用等学习总结

一、所谓‘锁’ 是什么 个人理解&#xff0c;所谓的锁就是为了保证数据库数据操作的一致性而产生的一种机制&#xff0c;即我们可能有很多数据&#xff0c;但是当我们有多个人或者多个线程或会话对同一条数据或同一批数据执行操作时&#xff0c;可能大家都要修改这一部分数据&…