使用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场景源码系统,并提供了完整的安…...

抖音小店入驻有什么条件?资金少,没经验的普通人做得起吗?
大家好,我是电商花花。 在直播电商的推动下,抖音小店独特的电商模式下吸引着众多的商家,吸引着一波又一波的创业者入驻,想要在抖音小店上开垦出属于自己的电商净土。 想要入驻抖音小店还需要一些条件,然后才能入驻成…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...