使用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场景源码系统,并提供了完整的安…...
抖音小店入驻有什么条件?资金少,没经验的普通人做得起吗?
大家好,我是电商花花。 在直播电商的推动下,抖音小店独特的电商模式下吸引着众多的商家,吸引着一波又一波的创业者入驻,想要在抖音小店上开垦出属于自己的电商净土。 想要入驻抖音小店还需要一些条件,然后才能入驻成…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
JS红宝书笔记 - 3.3 变量
要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...
Python的__call__ 方法
在 Python 中,__call__ 是一个特殊的魔术方法(magic method),它允许一个类的实例像函数一样被调用。当你在一个对象后面加上 () 并执行时(例如 obj()),Python 会自动调用该对象的 __call__ 方法…...
