使用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>
今天就分享到这里,感谢预览~
相关文章:
使用Android完成案例教学
目录 题目:完成在Android平台下2个玩家分别利用2个手机连接在同一局域网下通过滑动摇杆分别使红飞机和黄飞机移动的开发。(全代码解析) 题目:完成在Android平台下2个玩家分别利用2个手机连接在同一局域网下通过滑动摇杆分别使红飞…...
面向对象设计原则实验“依赖倒置原则”
高层模块不应该依赖于低层模块。二者都应该依赖于抽象。抽象不应该依赖于细节。细节应该依赖于抽象。 (开闭原则、里氏代换原则和依赖倒转原则的三个实例很相似,原因是它之间的关系很紧密,在实现很多重构时通常需要同时使用这三个原则。开闭…...
PMP考试到底难在哪里?
虽然PMP考试整体的并没有那么难,通过率也比较高,但PMP考试设计地非常巧妙,所以在面对考试时也不能掉以轻心。 01涉及面广 目前PMP考试内容大部分来源于教材《PMBOK指南》和《敏捷实践指南》。 作为考试出题的知识基础《PMBOK指南》&#x…...
Linux执行命令监控详细实现原理和使用教程,以及相关工具的使用
Linux执行命令监控详细实现原理和使用教程,以及相关工具的使用。 0x00 背景介绍 Linux上的HIDS需要实时对执行的命令进行监控,分析异常或入侵行为,有助于安全事件的发现和预防。为了获取执行命令,大致有如下方法: 遍…...
算法设计与分析实验报告c++实现(生命游戏、带锁的门、三壶谜题、串匹配问题、交替放置的碟子)
一、实验目的 1.加深学生对分治法算法设计方法的基本思想、基本步骤、基本方法的理解与掌握; 2.提高学生利用课堂所学知识解决实际问题的能力; 3.提高学生综合应用所学知识解决实际问题的能力。 二、实验任务 1、 编…...
【电子通识】热风枪的结构与使用方法
热风枪的结构 热风枪是专门用来拆焊、焊接贴片元器件和贴片集成电路的焊接工具,它主要由主机和热风焊枪两大部分构成。 热风枪主要有电源开关、风速设置、温度设置、热风连接等部件组成。根据不同品牌和价位的热风枪,有一些功能齐全的也集成了烙铁功能。…...
mysql知识点
MySQL 中有哪几种锁 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小&…...
css Animation 动画-右进左出
transform: rotate(旋转) | scale(缩放) | skew(倾斜) | translate(移动) ;<style> .jinggao {width: 60vw;display: inline-block;text-align: center;overflow: hidden;box-…...
第十三届蓝桥杯省赛大学B组填空题(c++)
A.扫雷 暴力模拟AC: #include<iostream> using namespace std; const int N105; int n,m,map[N][N],ans[N][N]; int dx[8]{-1,-1,0,1,1,1,0,-1}; int dy[8]{0,1,1,1,0,-1,-1,-1}; int count(int x,int y){int cnt0;for(int i0;i<8;i){int xxxdx[i];int yyydy[i];if(…...
天星金融(原小米金融)深耕金融知识领域,助力消费者提升金融素养
近年来,依托生活和消费品质不断提升的时代契机,信用卡持卡人的数量以及信用卡消费的频率不断增加,信用卡还款问题也日益凸显。部分不法分子打着“智能还款”、“精养提额”的口号“踏浪”入场,实则行诱导、诈骗之实。天星金融&…...
中国手机频段介绍
中国目前有三大运营商,分别是中国移动、中国联通、中国电信,还有一个潜在的运营商中国广电,各家使用的2/3/4G的制式略有不同 中国移动的GSM包括900M和1800M两个频段。 中国移动的4G的TD-LTE包括B34、B38、B39、B40、B41几个频段,…...
企业如何使用SNP Glue将SAP与Snowflake集成?
SNP Glue是SNP的集成技术,适用于任何云平台。它最初是围绕SAP和Hadoop构建的,现在已经发展为一个集成平台,虽然它仍然非常专注SAP,但可以将几乎任何数据源与任何数据目标集成。 我们客户非常感兴趣的数据目标之一是Snowflake。Sno…...
算法设计与分析实验报告c++实现(最近点对问题、循环赛日程安排问题、排序问题、棋盘覆盖问题)
一、实验目的 1.加深学生对分治法算法设计方法的基本思想、基本步骤、基本方法的理解与掌握; 2.提高学生利用课堂所学知识解决实际问题的能力; 3.提高学生综合应用所学知识解决实际问题的能力。 二、实验任务 1、最…...
Vue - 你知道Vue中computed和watch的区别吗
难度级别:中高级及以上 提问概率:70% 二者都是用来监听数据变化的,而且在日常工作中大部分时候都只是局限于简单实用,所以到了面试中很难全面说出二者的区别。接下来我们看一下,二者究竟有哪些区别呢? 先说computed,它的主要用途是监听…...
POJ2976 Dropping tests——P4377 [USACO18OPEN] Talent Show G 【分数规划二分法+贪心/背包】
POJ2976 Dropping tests 【分数规划二分法+贪心】 有 n 个物品,每个物品有两个权值 a 和b。你可以放弃 k 个物品,选 n-k 个物品,使得最大。 输入多个样例,第一行输入n 和 k,第二行输入n 个 ai ,第三行输入 n 个 bi,输入 0 0 结束。 输出答案乘100 后四舍五入到整数…...
【生产实习-毕设】pyspark学生成绩分析与预测(上)
注意:数据由实习单位老师提供(需要自行搜索下载),页面美化为下载模板。 项目介绍:前端页面输入影响成绩的属性,预测出成绩,并作可视化展示——属性对成绩的影响。使用python pyspark 进行数据预…...
【华为笔试题汇总】2024-04-10-华为春招笔试题(第二套)-三语言题解(CPP/Python/Java)
🍭 大家好这里是KK爱Coding ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为近期的春秋招笔试题汇总~ 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢…...
Windows 文件夹被占用无法删除
按下键盘上的“Ctrl Alt Delete”键打开任务管理器...
PHP+MySQL组合开发 易企秀H5场景源码系统 带完整的安装代码包以及搭建教程
在数字化时代,企业对于宣传与推广的需求日益增长,而H5页面作为一种轻量级、跨平台的宣传方式,深受企业青睐。为了满足企业对于H5页面制作的需求,我们基于PHPMySQL组合开发了一套易企秀H5场景源码系统,并提供了完整的安…...
抖音小店入驻有什么条件?资金少,没经验的普通人做得起吗?
大家好,我是电商花花。 在直播电商的推动下,抖音小店独特的电商模式下吸引着众多的商家,吸引着一波又一波的创业者入驻,想要在抖音小店上开垦出属于自己的电商净土。 想要入驻抖音小店还需要一些条件,然后才能入驻成…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
