├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── dictionaries
│ └── Liao.xml
├── encodings.xml
├── gradle.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
└── vcs.xml
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── kuoruan
│ │ └── bomberman
│ │ └── ExampleInstrumentationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── kuoruan
│ │ │ └── bomberman
│ │ │ ├── activity
│ │ │ ├── BaseActivity.java
│ │ │ ├── ConnectionActivity.java
│ │ │ ├── GameActivity.java
│ │ │ ├── MainActivity.java
│ │ │ ├── SplashActivity.java
│ │ │ └── WifiGameActivity.java
│ │ │ ├── adapter
│ │ │ ├── ChatAdapter.java
│ │ │ └── ConnectionAdapter.java
│ │ │ ├── dao
│ │ │ ├── GameDataDao.java
│ │ │ ├── GameLevelDataDao.java
│ │ │ └── GameOpenHelper.java
│ │ │ ├── entity
│ │ │ ├── BaseImage.java
│ │ │ ├── Bomb.java
│ │ │ ├── BombFire.java
│ │ │ ├── ChatContent.java
│ │ │ ├── Collision.java
│ │ │ ├── ConnectionItem.java
│ │ │ ├── DynamicImage.java
│ │ │ ├── GameTile.java
│ │ │ ├── GameUi.java
│ │ │ ├── Player.java
│ │ │ └── data
│ │ │ │ ├── GameData.java
│ │ │ │ └── GameLevelData.java
│ │ │ ├── net
│ │ │ ├── ConnectedService.java
│ │ │ └── ConnectingService.java
│ │ │ ├── util
│ │ │ ├── BitmapManager.java
│ │ │ ├── ConnectConstants.java
│ │ │ ├── DataUtil.java
│ │ │ ├── GameConstants.java
│ │ │ ├── PlayerManager.java
│ │ │ ├── SPUtils.java
│ │ │ └── SceneManager.java
│ │ │ └── view
│ │ │ └── GameView.java
│ └── res
│ │ ├── drawable-hdpi
│ │ ├── background.png
│ │ ├── bomb_1.png
│ │ ├── bomb_1_0.png
│ │ ├── bomb_1_1.png
│ │ ├── btn_circle_style.xml
│ │ ├── btn_white_style.xml
│ │ ├── ctrl_down_arrow.png
│ │ ├── ctrl_left_arrow.png
│ │ ├── ctrl_right_arrow.png
│ │ ├── ctrl_up_arrow.png
│ │ ├── fire.png
│ │ ├── game_bg.png
│ │ ├── player_1.png
│ │ ├── player_unit.png
│ │ ├── set_bomb.png
│ │ ├── tile_01.png
│ │ ├── tile_02.png
│ │ └── tile_03.png
│ │ ├── drawable-mdpi
│ │ ├── bomb_1.png
│ │ ├── bomb_1_0.png
│ │ ├── bomb_1_1.png
│ │ ├── ctrl_down_arrow.png
│ │ ├── ctrl_left_arrow.png
│ │ ├── ctrl_right_arrow.png
│ │ ├── ctrl_up_arrow.png
│ │ ├── fire.png
│ │ ├── game_bg.png
│ │ ├── player_1.png
│ │ ├── player_unit.png
│ │ ├── set_bomb.png
│ │ ├── tile_01.png
│ │ ├── tile_02.png
│ │ └── tile_03.png
│ │ ├── layout
│ │ ├── activity_connection.xml
│ │ ├── activity_main.xml
│ │ ├── chat_dialog.xml
│ │ ├── chat_item.xml
│ │ └── connection_item.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ ├── values-zh-rCN
│ │ └── strings.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── kuoruan
│ └── bomberman
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/dictionaries/Liao.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | Android API 19 Platform
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "24"
6 | defaultConfig {
7 | applicationId "com.kuoruan.bomberman"
8 | minSdkVersion 15
9 | targetSdkVersion 23
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(include: ['*.jar'], dir: 'libs')
23 | compile 'com.android.support:appcompat-v7:24.0.0'
24 | }
25 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\Android\Android-SDK/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/kuoruan/bomberman/ExampleInstrumentationTest.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.filters.MediumTest;
6 | import android.support.test.runner.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 |
12 | import static org.junit.Assert.*;
13 |
14 | /**
15 | * Instrumentation test, which will execute on an Android device.
16 | *
17 | * @see Testing documentation
18 | */
19 | @MediumTest
20 | @RunWith(AndroidJUnit4.class)
21 | public class ExampleInstrumentationTest {
22 | @Test
23 | public void useAppContext() throws Exception {
24 | // Context of the app under test.
25 | Context appContext = InstrumentationRegistry.getTargetContext();
26 |
27 | assertEquals("com.kuoruan.bomberman", appContext.getPackageName());
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
29 |
34 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/activity/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.activity;
2 |
3 |
4 | import android.os.Bundle;
5 | import android.support.v7.app.ActionBar;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.view.Gravity;
8 | import android.view.KeyEvent;
9 | import android.view.LayoutInflater;
10 | import android.view.MenuItem;
11 | import android.view.View;
12 |
13 | /**
14 | * Created by Liao on 2016/6/16 0016.
15 | */
16 |
17 | public abstract class BaseActivity extends AppCompatActivity {
18 |
19 | protected String TAG = this.getClass().getSimpleName();
20 | private ActionBar mActionBar;
21 | protected LayoutInflater mInflater;
22 |
23 | @Override
24 | protected void onCreate(Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 | onBeforeSetContentView();
27 | if (getLayoutId() != 0) {
28 | setContentView(getLayoutId());
29 | }
30 | mInflater = getLayoutInflater();
31 |
32 | if (hasActionBar()) {
33 | initActionBar();
34 | }
35 | init(savedInstanceState);
36 | }
37 |
38 | protected void initActionBar() {
39 | mActionBar = getSupportActionBar();
40 | if(mActionBar!=null) {
41 | //mActionBar.setBackgroundDrawable(getResources().getDrawable(R.color.actionbar_bg));
42 | mActionBar.setDisplayShowTitleEnabled(true);
43 | mActionBar.setDisplayUseLogoEnabled(true);
44 | if (hasBackButton()) {
45 | mActionBar.setDisplayShowHomeEnabled(false);
46 | mActionBar.setDisplayHomeAsUpEnabled(true);
47 | //mActionBar.setHomeAsUpIndicator(R.drawable.ic_launcher);
48 | }
49 | if (hasActionBarCustomView()) {
50 | mActionBar.setDisplayShowCustomEnabled(true);
51 | int layoutRes = getActionBarCustomViewLayoutRescId();
52 | View actionBarView = inflateView(layoutRes);
53 | ActionBar.LayoutParams params;
54 | if (isAllActionBarCustom()) {
55 | params = new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT,
56 | ActionBar.LayoutParams.MATCH_PARENT);
57 | } else {
58 | params = new ActionBar.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT,
59 | ActionBar.LayoutParams.MATCH_PARENT);
60 | params.gravity = Gravity.RIGHT;
61 | }
62 | mActionBar.setCustomView(actionBarView, params);
63 | handlerActionBarCustomViewAction(actionBarView);
64 | }
65 | }
66 | }
67 |
68 | @Override
69 | public boolean onOptionsItemSelected(MenuItem item) {
70 | switch (item.getItemId()) {
71 | case android.R.id.home:
72 | onBackAction();
73 | break;
74 | default:
75 | break;
76 | }
77 | return super.onOptionsItemSelected(item);
78 | }
79 |
80 | private void onBackAction() {
81 | onBackPressed();
82 | }
83 |
84 | protected void handlerActionBarCustomViewAction(View actionBarView) {
85 |
86 | }
87 |
88 | private View inflateView(int layoutRes) {
89 | return mInflater.inflate(layoutRes, null);
90 | }
91 |
92 | protected boolean hasActionBarCustomView() {
93 | return false;
94 | }
95 |
96 | protected boolean hasBackButton() {
97 | return true;
98 | }
99 |
100 | protected boolean hasActionBar() {
101 | return true;
102 | }
103 |
104 | protected void onBeforeSetContentView() {
105 | }
106 |
107 |
108 | protected abstract int getLayoutId();
109 |
110 | protected abstract void init(Bundle savedInstanceState);
111 |
112 | protected int getActionBarCustomViewLayoutRescId() {
113 | return 0;
114 | }
115 |
116 | protected boolean isAllActionBarCustom() {
117 | return false;
118 | }
119 |
120 | protected void setActionBarTitle(int resId) {
121 | if (resId != 0) {
122 | setActionBarTitle(getString(resId));
123 | }
124 | }
125 |
126 | protected void setActionBarTitle(String title) {
127 | if (hasActionBar()) {
128 | mActionBar.setTitle(title);
129 | }
130 | }
131 |
132 | @Override
133 | public boolean dispatchKeyEvent(KeyEvent event) {
134 | if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
135 | && event.getAction() == KeyEvent.ACTION_DOWN) {
136 | onBackAction();
137 | return true;
138 | }
139 | return super.dispatchKeyEvent(event);
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/activity/ConnectionActivity.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.activity;
2 |
3 | import android.app.Dialog;
4 | import android.app.ProgressDialog;
5 | import android.content.Context;
6 | import android.content.DialogInterface;
7 | import android.content.Intent;
8 | import android.net.wifi.WifiInfo;
9 | import android.net.wifi.WifiManager;
10 | import android.os.Bundle;
11 | import android.os.Handler;
12 | import android.os.Message;
13 | import android.support.v7.app.AlertDialog;
14 | import android.text.TextUtils;
15 | import android.util.Log;
16 | import android.view.View;
17 | import android.widget.AdapterView;
18 | import android.widget.Button;
19 | import android.widget.ListView;
20 | import android.widget.Toast;
21 |
22 | import com.kuoruan.bomberman.R;
23 | import com.kuoruan.bomberman.adapter.ChatAdapter;
24 | import com.kuoruan.bomberman.adapter.ConnectionAdapter;
25 | import com.kuoruan.bomberman.entity.ChatContent;
26 | import com.kuoruan.bomberman.entity.ConnectionItem;
27 | import com.kuoruan.bomberman.net.ConnectingService;
28 | import com.kuoruan.bomberman.util.ConnectConstants;
29 |
30 | import java.util.ArrayList;
31 | import java.util.List;
32 |
33 | /**
34 | * 对战大厅
35 | */
36 |
37 | public class ConnectionActivity extends BaseActivity implements View.OnClickListener {
38 | private List mConnections = new ArrayList<>();
39 | private ListView mListView;
40 | private ConnectionAdapter mAdapter;
41 | private String mIP;
42 | private ConnectingService mConnectingService;
43 | // 联机请求对话框
44 | private AlertDialog mConnectDialog;
45 | // 联机请求等待对话框
46 | private ProgressDialog waitDialog;
47 | // 显示聊天对话框
48 | private Dialog mChatDialog;
49 | private ChatAdapter mChatAdapter;
50 | private List mChats = new ArrayList<>();
51 | private ProgressDialog mScanDialog;
52 |
53 | @Override
54 | protected int getLayoutId() {
55 | return R.layout.activity_connection;
56 | }
57 |
58 | @Override
59 | protected void init(Bundle savedInstanceState) {
60 | mScanDialog = new ProgressDialog(this);
61 | mScanDialog.setMessage(getString(R.string.scan_loading));
62 | initView();
63 | initNet();
64 | }
65 |
66 | /**
67 | * 处理网络回调信息,刷新界面
68 | */
69 | private Handler mHandler = new Handler() {
70 |
71 | @Override
72 | public void handleMessage(Message msg) {
73 | switch (msg.what) {
74 | case ConnectConstants.ON_JOIN:
75 | ConnectionItem add = getConnectItem(msg);
76 | if (!mConnections.contains(add)) {
77 | mConnections.add(add);
78 | mAdapter.changeData(mConnections);
79 | }
80 | break;
81 | case ConnectConstants.ON_EXIT:
82 | ConnectionItem remove = getConnectItem(msg);
83 | if (mConnections.contains(remove)) {
84 | mConnections.remove(remove);
85 | mAdapter.changeData(mConnections);
86 | }
87 | break;
88 | case ConnectConstants.CONNECT_ASK:
89 | ConnectionItem ask = getConnectItem(msg);
90 | showConnectDialog(ask.name, ask.ip);
91 | break;
92 | case ConnectConstants.CONNECT_AGREE:
93 | if (waitDialog != null && waitDialog.isShowing()) {
94 | waitDialog.dismiss();
95 | }
96 | String ip = msg.peekData().getString("ip");
97 | Log.i(TAG, "handleMessage: " + ip);
98 |
99 | WifiGameActivity.startActivity(ConnectionActivity.this, false, ip);
100 | break;
101 | case ConnectConstants.CONNECT_REJECT:
102 | if (waitDialog != null && waitDialog.isShowing()) {
103 | waitDialog.dismiss();
104 | }
105 | Toast.makeText(ConnectionActivity.this, "对方拒绝了你的请求", Toast.LENGTH_LONG).show();
106 | default:
107 | break;
108 | }
109 | }
110 | };
111 |
112 | private void initView() {
113 | Button scan = (Button) findViewById(R.id.scan);
114 | scan.setOnClickListener(this);
115 | mListView = (ListView) findViewById(R.id.list);
116 | mAdapter = new ConnectionAdapter(this, mConnections);
117 | mListView.setAdapter(mAdapter);
118 | mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
119 |
120 | @Override
121 | public void onItemClick(AdapterView> parent, View v, int position, long id) {
122 | String ipDst = mConnections.get(position).ip;
123 | mConnectingService.sendAskConnect(ipDst);
124 | String title = "请求对战";
125 | String message = "等待" + ipDst + "回应.请稍后....";
126 | showProgressDialog(title, message);
127 | }
128 | });
129 | }
130 |
131 | private void initNet() {
132 | mIP = getIp();
133 | if (TextUtils.isEmpty(mIP)) {
134 | Toast.makeText(this, "请检查wifi连接后重试", Toast.LENGTH_LONG).show();
135 | finish();
136 | }
137 |
138 | }
139 |
140 | @Override
141 | protected void onStart() {
142 | super.onStart();
143 | mConnectingService = new ConnectingService(mIP, mHandler);
144 | mConnectingService.start();
145 | mConnectingService.sendScanMsg();
146 | }
147 |
148 | @Override
149 | protected void onStop() {
150 | super.onStop();
151 | mConnectingService.stop();
152 | mConnectingService.sendExitMsg();
153 | }
154 |
155 | /**
156 | * 从消息里面获取数据并生成ConnectionItem对象
157 | *
158 | * @param msg
159 | * @return ConnectionItem
160 | */
161 | private ConnectionItem getConnectItem(Message msg) {
162 | Bundle data = msg.peekData();
163 | String name = data.getString("name");
164 | String ip = data.getString("ip");
165 | ConnectionItem ci = new ConnectionItem(name, ip);
166 | return ci;
167 | }
168 |
169 | /**
170 | * 获取本机的ip地址,通过wifi连接局域网的情况
171 | *
172 | * @return ip地址
173 | */
174 | private String getIp() {
175 | WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
176 | // 检查Wifi状态
177 | if (!wm.isWifiEnabled()) {
178 | Log.d(TAG, "wifi is not enable,enable wifi first");
179 | return null;
180 | }
181 | WifiInfo wi = wm.getConnectionInfo();
182 | // 获取32位整型IP地址
183 | int ipAdd = wi.getIpAddress();
184 | // 把整型地址转换成“*.*.*.*”地址
185 | String ip = intToIp(ipAdd);
186 | Log.d(TAG, "ip:" + ip);
187 | return ip;
188 | }
189 |
190 | private String intToIp(int i) {
191 | return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF)
192 | + "." + (i >> 24 & 0xFF);
193 | }
194 |
195 | @Override
196 | public void onClick(View v) {
197 | switch (v.getId()) {
198 | case R.id.scan:
199 | mScanDialog.show();
200 | mConnectingService.sendScanMsg();
201 | break;
202 |
203 | default:
204 | break;
205 | }
206 | }
207 |
208 |
209 | private void showConnectDialog(String name, final String ip) {
210 | String msg = name + getString(R.string.fight_request);
211 | DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
212 |
213 | @Override
214 | public void onClick(DialogInterface dialog, int which) {
215 | switch (which) {
216 | case DialogInterface.BUTTON_POSITIVE:
217 | mConnectingService.accept(ip);
218 | WifiGameActivity.startActivity(ConnectionActivity.this, true, ip);
219 | break;
220 | case DialogInterface.BUTTON_NEGATIVE:
221 | mConnectingService.reject(ip);
222 | break;
223 | default:
224 | break;
225 | }
226 | }
227 |
228 | };
229 | if (mConnectDialog == null) {
230 | AlertDialog.Builder b = new AlertDialog.Builder(this);
231 | b.setCancelable(false);
232 | b.setMessage(msg);
233 | b.setPositiveButton(R.string.agree, listener);
234 | b.setNegativeButton(R.string.reject, listener);
235 | mConnectDialog = b.create();
236 | } else {
237 | mConnectDialog.setMessage(msg);
238 | mConnectDialog.setButton(DialogInterface.BUTTON_POSITIVE,
239 | getText(R.string.agree), listener);
240 | mConnectDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
241 | getText(R.string.reject), listener);
242 | }
243 | if (!mConnectDialog.isShowing()) {
244 | mConnectDialog.show();
245 | }
246 | }
247 |
248 | /**
249 | * 显示聊天内容对话框
250 | */
251 | private void showChatDialog() {
252 | if (mChatDialog == null) {
253 | AlertDialog.Builder b = new AlertDialog.Builder(this);
254 | b.setTitle("对话");
255 | View view = getLayoutInflater().inflate(R.layout.chat_dialog, null);
256 | ListView list = (ListView) view.findViewById(R.id.list_chat);
257 | mChatAdapter = new ChatAdapter(this, mChats);
258 | list.setAdapter(mChatAdapter);
259 | b.setView(view);
260 | mChatDialog = b.create();
261 | mChatDialog.show();
262 | } else {
263 | if (mChatDialog.isShowing()) {
264 | mChatAdapter.notifyDataSetChanged();
265 | } else {
266 | mChatDialog.show();
267 | }
268 | }
269 | }
270 |
271 | private void showProgressDialog(String title, String message) {
272 | if (waitDialog == null) {
273 | waitDialog = new ProgressDialog(this);
274 | }
275 | //waitDialog.setTitle(title);
276 | waitDialog.setMessage(message);
277 | waitDialog.setIndeterminate(true);
278 | waitDialog.setCancelable(true);
279 | waitDialog.show();
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/activity/GameActivity.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.activity;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.os.Handler;
6 | import android.os.Message;
7 | import android.util.Log;
8 | import android.view.Display;
9 | import android.view.Window;
10 | import android.widget.Toast;
11 |
12 | import com.kuoruan.bomberman.util.GameConstants;
13 | import com.kuoruan.bomberman.util.PlayerManager;
14 | import com.kuoruan.bomberman.util.SceneManager;
15 | import com.kuoruan.bomberman.view.GameView;
16 |
17 | /**
18 | * Created by Liao on 2016/5/1 0001.
19 | */
20 | public class GameActivity extends BaseActivity {
21 |
22 | private GameView mGameView = null;
23 | private PlayerManager mPlayerManager;
24 | private SceneManager mSceneManager;
25 |
26 | private Context mContext;
27 | private Handler mRefreshHandler = new Handler() {
28 | @Override
29 | public void handleMessage(Message msg) {
30 | Toast.makeText(mContext, "start...", Toast.LENGTH_LONG);
31 | super.handleMessage(msg);
32 | }
33 | };
34 |
35 | @Override
36 | protected int getLayoutId() {
37 | return 0;
38 | }
39 |
40 | @Override
41 | protected void init(Bundle savedInstanceState) {
42 | mContext = getApplicationContext();
43 |
44 | Display display = getWindowManager().getDefaultDisplay();
45 |
46 | int playerId = 1;
47 | mPlayerManager = new PlayerManager(mContext, mRefreshHandler, playerId);
48 | mSceneManager = new SceneManager(mContext, mRefreshHandler, GameConstants.MULTI_PLAYER_STAGE);
49 |
50 | mGameView = new GameView(mContext, mPlayerManager, mSceneManager, display);
51 |
52 | setContentView(mGameView);
53 | }
54 |
55 | @Override
56 | protected void onPause() {
57 | mGameView.getGameThread().setState(GameView.STATE_PAUSED);
58 | super.onPause();
59 | }
60 |
61 | @Override
62 | protected boolean hasActionBar() {
63 | return false;
64 | }
65 |
66 | @Override
67 | protected void onBeforeSetContentView() {
68 | requestWindowFeature(Window.FEATURE_NO_TITLE);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.activity;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.TextView;
7 |
8 | import com.kuoruan.bomberman.R;
9 |
10 | public class MainActivity extends BaseActivity implements View.OnClickListener {
11 | private static final String TAG = "MainActivity";
12 |
13 | private TextView tv_create_game;
14 | private TextView tv_join_game;
15 | private TextView tv_exit_game;
16 |
17 | @Override
18 | protected int getLayoutId() {
19 | return R.layout.activity_main;
20 | }
21 |
22 | @Override
23 | protected void init(Bundle savedInstanceState) {
24 | initView();
25 | }
26 |
27 | private void initView() {
28 | tv_create_game = (TextView) findViewById(R.id.bt_single_play);
29 | tv_join_game = (TextView) findViewById(R.id.bt_multi_game);
30 | tv_exit_game = (TextView) findViewById(R.id.bt_exit_game);
31 | tv_create_game.setOnClickListener(this);
32 | tv_join_game.setOnClickListener(this);
33 | tv_exit_game.setOnClickListener(this);
34 | }
35 |
36 | @Override
37 | public void onClick(View v) {
38 | switch (v.getId()) {
39 | case R.id.bt_single_play:
40 | startActivity(new Intent(this, GameActivity.class));
41 | break;
42 | case R.id.bt_multi_game:
43 | startActivity(new Intent(this, ConnectionActivity.class));
44 | break;
45 | }
46 | }
47 |
48 | @Override
49 | protected boolean hasBackButton() {
50 | return false;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/activity/SplashActivity.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.activity;
2 |
3 | import android.os.Bundle;
4 |
5 | /**
6 | * Created by Liao on 2016/6/16 0016.
7 | */
8 |
9 | public class SplashActivity extends BaseActivity {
10 |
11 | @Override
12 | protected int getLayoutId() {
13 | return 0;
14 | }
15 |
16 | @Override
17 | protected void init(Bundle savedInstanceState) {
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/activity/WifiGameActivity.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.activity;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.os.Handler;
8 | import android.os.Message;
9 | import android.text.TextUtils;
10 | import android.util.Log;
11 | import android.view.Display;
12 | import android.view.Window;
13 | import android.widget.Toast;
14 |
15 | import com.kuoruan.bomberman.net.ConnectedService;
16 | import com.kuoruan.bomberman.util.ConnectConstants;
17 | import com.kuoruan.bomberman.util.GameConstants;
18 | import com.kuoruan.bomberman.util.PlayerManager;
19 | import com.kuoruan.bomberman.util.SceneManager;
20 | import com.kuoruan.bomberman.view.GameView;
21 |
22 | import org.json.JSONObject;
23 |
24 | /**
25 | * Created by Liao on 2016/6/16 0016.
26 | */
27 | public class WifiGameActivity extends BaseActivity {
28 |
29 | private GameView mGameView;
30 | private PlayerManager mPlayerManager;
31 | private SceneManager mSceneManager;
32 |
33 | private Context mContext;
34 | private boolean mIsServer;
35 | private String mDstIp;
36 | private ProgressDialog mWaitDialog;
37 | private ConnectedService mConnectedService;
38 |
39 | /**
40 | * 处理游戏回调信息,刷新界面
41 | */
42 | private Handler mRefreshHandler = new Handler() {
43 |
44 | @Override
45 | public void handleMessage(Message msg) {
46 | JSONObject jsonObject = (JSONObject) msg.obj;
47 | switch (msg.what) {
48 | case GameConstants.PLAYER_ADD:
49 | case GameConstants.PLAYER_MOVE:
50 | case GameConstants.PLAYER_STOP:
51 | case GameConstants.PLAYER_DIE:
52 | case GameConstants.SET_BOMB:
53 | mConnectedService.sendTCPData(jsonObject);
54 | break;
55 | default:
56 | break;
57 | }
58 | }
59 | };
60 |
61 | /**
62 | * 处理网络信息,更新界面
63 | */
64 | private Handler mRequestHandler = new Handler() {
65 |
66 | @Override
67 | public void handleMessage(Message msg) {
68 | JSONObject jsonObject = (JSONObject) msg.obj;
69 | switch (msg.what) {
70 | case ConnectConstants.GAME_CONNECTED:
71 | mWaitDialog.dismiss();
72 | break;
73 | case GameConstants.PLAYER_ADD:
74 | mPlayerManager.handlePlayerAdd(jsonObject);
75 | break;
76 | case GameConstants.PLAYER_MOVE:
77 | mPlayerManager.handlePlayerMove(jsonObject);
78 | break;
79 | case GameConstants.PLAYER_STOP:
80 | mPlayerManager.handlePlayerStop(jsonObject);
81 | break;
82 | case GameConstants.PLAYER_DIE:
83 | mPlayerManager.handlePlayerDie(jsonObject);
84 | break;
85 | case GameConstants.SET_BOMB:
86 | mSceneManager.handleSetBomb(jsonObject);
87 | break;
88 | default:
89 | break;
90 | }
91 | }
92 | };
93 |
94 |
95 | public static void startActivity(Context context, boolean isServer, String dstIp) {
96 | Intent intent = new Intent(context, WifiGameActivity.class);
97 | Bundle b = new Bundle();
98 | b.putBoolean("isServer", isServer);
99 | b.putString("ip", dstIp);
100 | intent.putExtras(b);
101 | context.startActivity(intent);
102 | }
103 |
104 | @Override
105 | protected int getLayoutId() {
106 | return 0;
107 | }
108 |
109 | @Override
110 | protected void init(Bundle savedInstanceState) {
111 | Bundle b = getIntent().getExtras();
112 | if (b == null) {
113 | Toast.makeText(this, "建立网络失败,请重试", Toast.LENGTH_SHORT).show();
114 | finish();
115 | }
116 |
117 | showProgressDialog(null, "建立连接中,请稍后");
118 | mContext = getApplicationContext();
119 | mIsServer = b.getBoolean("isServer");
120 | mDstIp = b.getString("ip");
121 | initGame();
122 | }
123 |
124 | private void initGame() {
125 | Display display = getWindowManager().getDefaultDisplay();
126 | mConnectedService = new ConnectedService(mRequestHandler, mDstIp, mIsServer); // TCP连接
127 | int playerId = mIsServer ? 1 : 2;
128 |
129 | mPlayerManager = new PlayerManager(mContext, mRefreshHandler, playerId);
130 | mSceneManager = new SceneManager(mContext, mRefreshHandler, GameConstants.MULTI_PLAYER_STAGE);
131 |
132 | mGameView = new GameView(mContext, mPlayerManager, mSceneManager, display);
133 |
134 | setContentView(mGameView);
135 | }
136 |
137 | @Override
138 | protected void onPause() {
139 | mGameView.getGameThread().setState(GameView.STATE_PAUSED);
140 | super.onPause();
141 | }
142 |
143 | @Override
144 | protected boolean hasActionBar() {
145 | return false;
146 | }
147 |
148 | @Override
149 | protected void onBeforeSetContentView() {
150 | requestWindowFeature(Window.FEATURE_NO_TITLE);
151 | }
152 |
153 | private void showProgressDialog(String title, String message) {
154 | if (mWaitDialog == null) {
155 | mWaitDialog = new ProgressDialog(this);
156 | }
157 | if (!TextUtils.isEmpty(title)) {
158 | mWaitDialog.setTitle(title);
159 | }
160 | mWaitDialog.setMessage(message);
161 | mWaitDialog.setIndeterminate(true);
162 | mWaitDialog.setCancelable(true);
163 | mWaitDialog.show();
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/adapter/ChatAdapter.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.adapter;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 |
10 | import com.kuoruan.bomberman.R;
11 | import com.kuoruan.bomberman.entity.ChatContent;
12 |
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | public class ChatAdapter extends BaseAdapter {
17 | private List mData = new ArrayList<>();
18 | private Context mContext;
19 |
20 | public ChatAdapter(Context context, List data) {
21 | mContext = context;
22 | mData = data;
23 | }
24 |
25 | @Override
26 | public int getCount() {
27 | return mData.size();
28 | }
29 |
30 | @Override
31 | public Object getItem(int position) {
32 | return mData.get(position);
33 | }
34 |
35 | @Override
36 | public long getItemId(int position) {
37 | return 0;
38 | }
39 |
40 | @Override
41 | public View getView(int position, View convertView, ViewGroup parent) {
42 | ViewHolder holder;
43 | if (convertView == null) {
44 | LayoutInflater inflate = (LayoutInflater) mContext
45 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
46 | convertView = inflate.inflate(R.layout.chat_item, null);
47 | holder = new ViewHolder();
48 | holder.title = (TextView) convertView.findViewById(R.id.title);
49 | holder.content = (TextView) convertView.findViewById(R.id.content);
50 | holder.time = (TextView) convertView.findViewById(R.id.time);
51 | convertView.setTag(holder);
52 | } else {
53 | holder = (ViewHolder) convertView.getTag();
54 | }
55 | int count = getCount() - 1;
56 | ChatContent item = mData.get(count - position);
57 | holder.title.setText(item.connector.name + "(" + item.connector.ip
58 | + ")");
59 | holder.content.setText(item.content);
60 | holder.time.setText(item.time);
61 | return convertView;
62 | }
63 |
64 | public void changeData(List data) {
65 | mData = data;
66 | notifyDataSetChanged();
67 | }
68 |
69 | class ViewHolder {
70 | TextView title;
71 | TextView content;
72 | TextView time;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/adapter/ConnectionAdapter.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.adapter;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 |
10 | import com.kuoruan.bomberman.R;
11 | import com.kuoruan.bomberman.entity.ConnectionItem;
12 |
13 | import java.util.List;
14 |
15 | public class ConnectionAdapter extends BaseAdapter {
16 | private List mData;
17 | private Context mContext;
18 |
19 | public ConnectionAdapter(Context context, List data) {
20 | this.mContext = context;
21 | this.mData = data;
22 | }
23 |
24 | @Override
25 | public int getCount() {
26 | if (mData != null) {
27 | return mData.size();
28 | }
29 | return 0;
30 | }
31 |
32 | @Override
33 | public ConnectionItem getItem(int position) {
34 | if (mData != null) {
35 | return mData.get(position);
36 | }
37 | return null;
38 | }
39 |
40 | @Override
41 | public long getItemId(int position) {
42 | return 0;
43 | }
44 |
45 | @Override
46 | public View getView(int position, View convertView, ViewGroup parent) {
47 | ViewHolder holder;
48 | if (convertView == null) {
49 | LayoutInflater inflate = (LayoutInflater) mContext
50 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
51 | convertView = inflate.inflate(R.layout.connection_item, null);
52 | holder = new ViewHolder();
53 | holder.name = (TextView) convertView.findViewById(R.id.name);
54 | holder.ip = (TextView) convertView.findViewById(R.id.ip);
55 | convertView.setTag(holder);
56 | } else {
57 | holder = (ViewHolder) convertView.getTag();
58 | }
59 | ConnectionItem item = mData.get(position);
60 | holder.name.setText(mContext.getString(R.string.game_player) + item.name);
61 | holder.ip.setText("IP地址" + item.ip);
62 | return convertView;
63 | }
64 |
65 | public void changeData(List data) {
66 | mData = data;
67 | notifyDataSetChanged();
68 | }
69 |
70 | class ViewHolder {
71 | TextView name;
72 | TextView ip;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/dao/GameDataDao.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.dao;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.database.sqlite.SQLiteDatabase;
6 |
7 | import com.kuoruan.bomberman.entity.GameTile;
8 | import com.kuoruan.bomberman.entity.data.GameData;
9 |
10 | import java.util.ArrayList;
11 | import java.util.HashMap;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | import static android.provider.BaseColumns._ID;
16 |
17 | /**
18 | * Created by Liao on 2016/5/1 0001.
19 | */
20 | public class GameDataDao {
21 |
22 | public static final String TABLE_NAME = "gameUnitData";
23 |
24 | public static final String TYPE = "type";
25 | public static final String SUB_TYPE = "subType";
26 | public static final String DRAWABLE = "drawable";
27 | public static final String VISIBLE = "visible";
28 |
29 | //图片类型
30 | public static final int TYPE_TILE = 1;
31 | public static final int TYPE_PLAYER = 2;
32 | public static final int TYPE_BOMB = 3;
33 | public static final int TYPE_BOMB_FIRE = 4;
34 |
35 | public static final int FIELD_ID_ID = 0;
36 | public static final int FIELD_ID_TYPE = 1;
37 | public static final int FIELD_ID_SUB_TYPE = 2;
38 | public static final int FIELD_ID_DRAWABLE = 3;
39 | public static final int FIELD_ID_VISIBLE = 4;
40 |
41 | private GameOpenHelper mGameOpenHelper;
42 | private Context mContext;
43 | private static GameDataDao mGameData;
44 |
45 | private GameDataDao(Context context) {
46 | this.mContext = context;
47 | mGameOpenHelper = new GameOpenHelper(context);
48 | }
49 |
50 | public static GameDataDao getInstance(Context context) {
51 | if (mGameData == null) {
52 | synchronized (GameDataDao.class) {
53 | if (mGameData == null) {
54 | mGameData = new GameDataDao(context);
55 | }
56 | }
57 | }
58 | return mGameData;
59 | }
60 |
61 | public Map getGameTileData() {
62 | SQLiteDatabase db = mGameOpenHelper.getReadableDatabase();
63 |
64 | String[] from = {_ID, TYPE, SUB_TYPE, DRAWABLE, VISIBLE};
65 | String where = TYPE + " = " + TYPE_TILE;
66 |
67 | Cursor cursor = db.query(TABLE_NAME, from, where, null, null, null, null);
68 |
69 | Map data = new HashMap<>();
70 |
71 | while (cursor.moveToNext()) {
72 | GameData tileData = new GameData();
73 | tileData.setId(cursor.getInt(FIELD_ID_ID));
74 | tileData.setType(cursor.getInt(FIELD_ID_TYPE));
75 | int subType = cursor.getInt(FIELD_ID_SUB_TYPE);
76 | tileData.setSubType(subType);
77 | tileData.setDrawable(cursor.getInt(FIELD_ID_DRAWABLE));
78 | int visible = cursor.getInt(FIELD_ID_VISIBLE);
79 | tileData.setVisible(visible == 1);
80 | data.put(subType, tileData);
81 | }
82 | cursor.close();
83 | db.close();
84 |
85 | return data;
86 | }
87 |
88 | public Map getPlayerData() {
89 | SQLiteDatabase db = mGameOpenHelper.getReadableDatabase();
90 |
91 | String[] from = {_ID, TYPE, SUB_TYPE, DRAWABLE};
92 | String where = TYPE + " = " + TYPE_PLAYER;
93 |
94 | Cursor cursor = db.query(TABLE_NAME, from, where, null, null, null, null);
95 | Map data = new HashMap<>();
96 |
97 | while (cursor.moveToNext()) {
98 | GameData playerData = new GameData();
99 |
100 | playerData.setId(cursor.getInt(FIELD_ID_ID));
101 | playerData.setType(cursor.getInt(FIELD_ID_TYPE));
102 | int id = cursor.getInt(FIELD_ID_SUB_TYPE);
103 | playerData.setSubType(id);
104 | playerData.setDrawable(cursor.getInt(FIELD_ID_DRAWABLE));
105 |
106 | data.put(id, playerData);
107 | }
108 |
109 | cursor.close();
110 | db.close();
111 |
112 | return data;
113 | }
114 |
115 | public Map getBombData() {
116 | SQLiteDatabase db = mGameOpenHelper.getReadableDatabase();
117 | String[] from = {_ID, TYPE, SUB_TYPE, DRAWABLE};
118 | String where = TYPE + " = " + TYPE_BOMB;
119 |
120 | Cursor cursor = db.query(TABLE_NAME, from, where, null, null, null, null);
121 |
122 | Map data = new HashMap<>();
123 |
124 | while (cursor.moveToNext()) {
125 | GameData bombData = new GameData();
126 | bombData.setId(cursor.getInt(FIELD_ID_ID));
127 | bombData.setType(cursor.getInt(FIELD_ID_TYPE));
128 | int subType = cursor.getInt(FIELD_ID_SUB_TYPE);
129 | bombData.setSubType(subType);
130 | bombData.setDrawable(cursor.getInt(FIELD_ID_DRAWABLE));
131 |
132 | data.put(subType, bombData);
133 | }
134 |
135 | cursor.close();
136 | db.close();
137 |
138 | return data;
139 | }
140 |
141 | public Map getFireData() {
142 | SQLiteDatabase db = mGameOpenHelper.getReadableDatabase();
143 | String[] from = {_ID, TYPE, SUB_TYPE, DRAWABLE};
144 | String where = TYPE + " = " + TYPE_BOMB_FIRE;
145 | Cursor cursor = db.query(TABLE_NAME, from, where, null, null, null, null);
146 |
147 | Map data = new HashMap<>();
148 |
149 | while (cursor.moveToNext()) {
150 | GameData fireData = new GameData();
151 | fireData.setId(cursor.getInt(FIELD_ID_ID));
152 | fireData.setType(cursor.getInt(FIELD_ID_TYPE));
153 | int subType = cursor.getInt(FIELD_ID_SUB_TYPE);
154 | fireData.setSubType(subType);
155 | fireData.setDrawable(cursor.getInt(FIELD_ID_DRAWABLE));
156 |
157 | data.put(subType, fireData);
158 | }
159 | cursor.close();
160 | db.close();
161 |
162 | return data;
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/dao/GameLevelDataDao.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.dao;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.database.sqlite.SQLiteDatabase;
6 |
7 | import com.kuoruan.bomberman.entity.data.GameLevelData;
8 |
9 | import static android.provider.BaseColumns._ID;
10 |
11 | /**
12 | * Created by Liao on 2016/5/2 0002.
13 | */
14 | public class GameLevelDataDao {
15 | public static final String TABLE_NAME = "gameLevelTileData";
16 |
17 | public static final String STAGE = "stage";
18 | public static final String PLAYER_START_TILE_X = "playerStartX";
19 | public static final String PLAYER_START_TILE_Y = "playerStartY";
20 | public static final String TILE_DATA = "tileData";
21 |
22 | public static final int FIELD_ID_ID = 0;
23 | public static final int FIELD_ID_STAGE = 1;
24 | public static final int FIELD_ID_PLAYER_START_X = 2;
25 | public static final int FIELD_ID_PLAYER_START_Y = 3;
26 | public static final int FIELD_ID_TILE_DATA = 4;
27 |
28 | public static final String TILE_DATA_LINE_BREAK = "//";
29 |
30 | private static GameLevelDataDao mGameLevelTileDao;
31 | private GameOpenHelper mGameOpenHelper;
32 | private Context mContext;
33 |
34 | private GameLevelDataDao(Context context) {
35 | mGameOpenHelper = new GameOpenHelper(context);
36 | this.mContext = context;
37 | }
38 |
39 | public static GameLevelDataDao getInstance(Context context) {
40 | if (mGameLevelTileDao == null) {
41 | synchronized (GameLevelDataDao.class) {
42 | if (mGameLevelTileDao == null) {
43 | mGameLevelTileDao = new GameLevelDataDao(context);
44 | }
45 | }
46 | }
47 |
48 | return mGameLevelTileDao;
49 | }
50 |
51 | /**
52 | * 获取关卡地图数据集合
53 | *
54 | * @param stage 关卡
55 | * @return ArrayList
56 | */
57 | public GameLevelData getGameLevelData(int stage) {
58 |
59 | SQLiteDatabase db = mGameOpenHelper.getReadableDatabase();
60 |
61 | String[] from = {_ID, STAGE, PLAYER_START_TILE_X, PLAYER_START_TILE_Y, TILE_DATA};
62 | String where = STAGE + " = " + stage;
63 |
64 | Cursor cursor = db.query(TABLE_NAME, from, where, null, null, null, null);
65 |
66 | GameLevelData gameLevelData = null;
67 | if (cursor.moveToNext()) {
68 | gameLevelData = new GameLevelData();
69 | gameLevelData.setId(cursor.getInt(FIELD_ID_ID));
70 | gameLevelData.setPlayerStartX(cursor.getInt(FIELD_ID_PLAYER_START_X));
71 | gameLevelData.setPlayerStartY(cursor.getInt(FIELD_ID_PLAYER_START_Y));
72 | gameLevelData.setStage(cursor.getInt(FIELD_ID_STAGE));
73 | gameLevelData.setLevelTiles(cursor.getString(FIELD_ID_TILE_DATA));
74 | }
75 | cursor.close();
76 | db.close();
77 | return gameLevelData;
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/dao/GameOpenHelper.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.dao;
2 |
3 | import android.content.Context;
4 | import android.database.sqlite.SQLiteDatabase;
5 | import android.database.sqlite.SQLiteOpenHelper;
6 |
7 | import com.kuoruan.bomberman.R;
8 | import com.kuoruan.bomberman.entity.Bomb;
9 | import com.kuoruan.bomberman.entity.BombFire;
10 | import com.kuoruan.bomberman.entity.GameTile;
11 | import com.kuoruan.bomberman.util.GameConstants;
12 |
13 | import static android.provider.BaseColumns._ID;
14 |
15 | /**
16 | * Created by Liao on 2016/5/2 0002.
17 | */
18 | public class GameOpenHelper extends SQLiteOpenHelper {
19 |
20 | private static final String DB_NAME = "bomberman.db";
21 | private static final int DB_VERSION = 1;
22 |
23 | public GameOpenHelper(Context context) {
24 | super(context, DB_NAME, null, DB_VERSION);
25 | }
26 |
27 | @Override
28 | public void onCreate(SQLiteDatabase db) {
29 | db.execSQL(CREATE_TABLE_GAME_DATA);
30 | db.execSQL(CREATE_TABLE_GAME_LEVEL_TILES);
31 |
32 | for (String query : POPULATE_TABLE_GAME_DATA) {
33 | db.execSQL(query);
34 | }
35 |
36 | for (String query : POPULATE_TABLE_GAME_LEVEL_TILES) {
37 | db.execSQL(query);
38 | }
39 | }
40 |
41 | @Override
42 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
43 | db.execSQL("DROP TABLE IF EXISTS " + GameDataDao.TABLE_NAME);
44 | db.execSQL("DROP TABLE IF EXISTS " + GameLevelDataDao.TABLE_NAME);
45 |
46 | onCreate(db);
47 | }
48 |
49 | private static final String CREATE_TABLE_GAME_DATA = "CREATE TABLE " + GameDataDao.TABLE_NAME + " ("
50 | + _ID + " INTEGER PRIMARY KEY, "
51 | + GameDataDao.TYPE + " INTEGER DEFAULT 1,"
52 | + GameDataDao.SUB_TYPE + " INTEGER DEFAULT 0,"
53 | + GameDataDao.DRAWABLE + " INTEGER DEFAULT 0,"
54 | + GameDataDao.VISIBLE + " INTEGER DEFAULT 1"
55 | + ");";
56 |
57 | private static final String CREATE_TABLE_GAME_LEVEL_TILES = "CREATE TABLE " + GameLevelDataDao.TABLE_NAME + " ("
58 | + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
59 | + GameLevelDataDao.STAGE + " INTEGER DEFAULT 0,"
60 | + GameLevelDataDao.PLAYER_START_TILE_X + " INTEGER DEFAULT 0,"
61 | + GameLevelDataDao.PLAYER_START_TILE_Y + " INTEGER DEFAULT 0,"
62 | + GameLevelDataDao.TILE_DATA + " TEXT NOT NULL"
63 | + ");";
64 |
65 | private static final String[] POPULATE_TABLE_GAME_DATA = {
66 | "INSERT INTO " + GameDataDao.TABLE_NAME + " VALUES "
67 | + "(1," + GameDataDao.TYPE_TILE + "," + GameTile.TYPE_OBSTACLE + "," + R.drawable.tile_01 + ",1);",
68 |
69 | "INSERT INTO " + GameDataDao.TABLE_NAME + " VALUES "
70 | + "(2," + GameDataDao.TYPE_TILE + "," + GameTile.TYPE_ROCK + "," + R.drawable.tile_02 + ",1);",
71 |
72 | "INSERT INTO " + GameDataDao.TABLE_NAME + " VALUES "
73 | + "(3," + GameDataDao.TYPE_TILE + "," + GameTile.TYPE_CRATES + "," + R.drawable.tile_03 + ",1);",
74 |
75 | "INSERT INTO " + GameDataDao.TABLE_NAME + " VALUES "
76 | + "(4," + GameDataDao.TYPE_PLAYER + ",1," + R.drawable.player_1 + ",1);",
77 |
78 | "INSERT INTO " + GameDataDao.TABLE_NAME + " VALUES "
79 | + "(5," + GameDataDao.TYPE_PLAYER + ",2," + R.drawable.player_1 + ",1);",
80 |
81 | "INSERT INTO " + GameDataDao.TABLE_NAME + " VALUES "
82 | + "(6," + GameDataDao.TYPE_BOMB + "," + Bomb.NORMAL + "," + R.drawable.bomb_1 + ",1);",
83 |
84 | "INSERT INTO " + GameDataDao.TABLE_NAME + " VALUES "
85 | + "(7," + GameDataDao.TYPE_BOMB_FIRE + "," + BombFire.NORMAL + "," + R.drawable.fire + ",1);",
86 | };
87 |
88 | private static final String[] POPULATE_TABLE_GAME_LEVEL_TILES = {
89 | "INSERT INTO " + GameLevelDataDao.TABLE_NAME + " VALUES "
90 | + "(null," + GameConstants.MULTI_PLAYER_STAGE + ",1,1,\""
91 | // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
92 | /* 1 */ + "01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
93 | /* 2 */ + "01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
94 | /* 3 */ + "01,00,02,00,02,00,02,00,02,00,02,00,02,00,02,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
95 | /* 4 */ + "01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
96 | /* 5 */ + "01,00,02,00,02,00,02,00,02,00,02,00,02,00,02,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
97 | /* 6 */ + "01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
98 | /* 7 */ + "01,00,02,00,02,00,02,00,02,00,02,00,02,00,02,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
99 | /* 8 */ + "01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
100 | /* 9 */ + "01,00,02,00,02,00,02,00,02,00,02,00,02,00,02,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
101 | /* 10 */ + "01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
102 | /* 11 */ + "01,00,02,00,02,00,02,00,02,00,02,00,02,00,02,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
103 | /* 12 */ + "01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
104 | /* 13 */ + "01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01" + GameLevelDataDao.TILE_DATA_LINE_BREAK
105 | + "\");"
106 | };
107 | }
108 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/BaseImage.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Point;
5 |
6 | /**
7 | * 基本图片类,为所有游戏对象基类
8 | */
9 |
10 | public class BaseImage {
11 | protected Bitmap mBitmap;
12 | protected int mWidth = 0;
13 | protected int mHeight = 0;
14 | protected Point mPoint = new Point();
15 |
16 | public BaseImage() {
17 |
18 | }
19 |
20 | public BaseImage(Bitmap bitmap) {
21 | this.mBitmap = bitmap;
22 | this.mWidth = bitmap.getWidth();
23 | this.mHeight = bitmap.getHeight();
24 | }
25 |
26 | public BaseImage(Bitmap bitmap, Point point) {
27 | this(bitmap);
28 | this.mPoint = point;
29 | }
30 |
31 | public Bitmap getBitmap() {
32 | return mBitmap;
33 | }
34 |
35 | public void setBitmap(Bitmap bitmap) {
36 | if (bitmap != null) {
37 | this.mBitmap = bitmap;
38 | this.mWidth = bitmap.getWidth();
39 | this.mHeight = bitmap.getHeight();
40 | }
41 | }
42 |
43 | public void setBitmap(Bitmap bitmap, int width, int height) {
44 | if (bitmap != null) {
45 | this.mBitmap = bitmap;
46 | setWidthAndHeight(width, height);
47 | }
48 | }
49 |
50 | //设置需要的图片宽和高
51 | private void setWidthAndHeight(int width, int height) {
52 | if (mBitmap != null) {
53 | this.mWidth = (width > 0) ? width : mBitmap.getWidth();
54 | this.mHeight = (height > 0) ? height : ((width > 0) ? width : mBitmap.getHeight());
55 | }
56 | }
57 |
58 | public int getWidth() {
59 | return mWidth;
60 | }
61 |
62 | public void setWidth(int width) {
63 | mWidth = width;
64 | }
65 |
66 | public int getHeight() {
67 | return mHeight;
68 | }
69 |
70 | public void setHeight(int height) {
71 | mHeight = height;
72 | }
73 |
74 | public int getX() {
75 | return mPoint.x;
76 | }
77 |
78 | public void setX(int x) {
79 | mPoint.x = x;
80 | }
81 |
82 | public int getY() {
83 | return mPoint.y;
84 | }
85 |
86 | public void setY(int y) {
87 | mPoint.y = y;
88 | }
89 |
90 | public void setCenterX(int centerX) {
91 | mPoint.x = (centerX - (this.getWidth() / 2));
92 | }
93 |
94 | public int getCenterX() {
95 | return (mPoint.x + (this.getWidth() / 2));
96 | }
97 |
98 | public void setCenterY(int centerY) {
99 | mPoint.y = (centerY - (this.getHeight() / 2));
100 | }
101 |
102 | public int getCenterY() {
103 | return (mPoint.y + (this.getHeight() / 2));
104 | }
105 |
106 | public void setPoint(Point point) {
107 | mPoint.x = point.x;
108 | mPoint.y = point.y;
109 | }
110 |
111 | public Point getPoint() {
112 | return mPoint;
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/Bomb.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Point;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * Created by Liao on 2016/5/3 0003.
10 | */
11 | public class Bomb extends GameTile {
12 |
13 | /**
14 | * 炸弹类型
15 | */
16 | public static final int NORMAL = 1;
17 | /**
18 | * 默认爆炸时间,毫秒
19 | */
20 | public static final int DEFAULT_EXPLOSION_TIME = 3000;
21 | /**
22 | * 默认火焰长度
23 | */
24 | public static final int DEFAULT_FIRE_LENGTH = 3;
25 |
26 | private long id;
27 | private int pid;
28 | private int mExplosionTime = DEFAULT_EXPLOSION_TIME;
29 | private boolean mExplosion = false;
30 | private int mFireLength = DEFAULT_FIRE_LENGTH;
31 |
32 | public Bomb(List frameBitmap, boolean isLoop, Point point, int pid) {
33 | super(frameBitmap, isLoop, point, GameTile.TYPE_BOMB);
34 | this.id = System.currentTimeMillis();
35 | this.pid = pid;
36 | new BombThread().start();
37 | }
38 |
39 | public Bomb(List frameBitmap, boolean isLoop, Point point, long id, int pid) {
40 | this(frameBitmap, isLoop, point, pid);
41 | this.id = id;
42 | }
43 |
44 | public long getId() {
45 | return id;
46 | }
47 |
48 | class BombThread extends Thread {
49 | @Override
50 | public void run() {
51 | try {
52 | Thread.sleep(mExplosionTime);
53 | } catch (InterruptedException e) {
54 | e.printStackTrace();
55 | }
56 |
57 | if (!mExplosion) {
58 | mExplosion = true;
59 | }
60 | }
61 | }
62 |
63 | public int getExplosionTime() {
64 | return mExplosionTime;
65 | }
66 |
67 | public void setExplosionTime(int explosionTime) {
68 | this.mExplosionTime = explosionTime;
69 | }
70 |
71 | public void setExplosion(boolean explosion) {
72 | mExplosion = explosion;
73 | }
74 |
75 | public boolean isExplosion() {
76 | return mExplosion;
77 | }
78 |
79 | public int getFireLength() {
80 | return mFireLength;
81 | }
82 |
83 | public void setFireLength(int fireLength) {
84 | mFireLength = fireLength;
85 | }
86 |
87 | public int getPid() {
88 | return pid;
89 | }
90 |
91 | public void setPid(int pid) {
92 | this.pid = pid;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/BombFire.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Point;
5 |
6 | import com.kuoruan.bomberman.util.SceneManager;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * Created by Liao on 2016/5/8 0008.
12 | */
13 | public class BombFire extends GameTile {
14 |
15 | public static final int NORMAL = 1;
16 |
17 | public static final int TYPE_UP = 1;
18 | public static final int TYPE_DOWN = 2;
19 | public static final int TYPE_LEFT = 3;
20 | public static final int TYPE_RIGHT = 4;
21 | public static final int TYPE_VERTICAL = 5;
22 | public static final int TYPE_HORIZONTAL = 6;
23 | public static final int TYPE_CENTER = 7;
24 |
25 | public BombFire(List frameBitmap) {
26 | super(frameBitmap, GameTile.TYPE_BOMB_FIRE);
27 | this.mWidth = SceneManager.tileWidth;
28 | this.mHeight = SceneManager.tileHeight;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/ChatContent.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.util.Date;
5 | import java.util.Locale;
6 |
7 | public class ChatContent {
8 | public ConnectionItem connector;
9 | public String content;
10 | public String time;
11 | public static final String FORMAT = "yyyy-M-d HH:mm:ss";
12 |
13 | public ChatContent(ConnectionItem ci, String content) {
14 | this.connector = ci;
15 | this.content = content;
16 | this.time = new SimpleDateFormat(FORMAT, Locale.getDefault()).format(new Date());
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/Collision.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity;
2 |
3 | /**
4 | * 角色和地图冲突对象
5 | */
6 | public class Collision {
7 | private static final String TAG = "Conflict";
8 | public static final int SOLVE_LENGTH = 15;
9 | private GameTile mCollisionTile;
10 | private boolean mSolvable;
11 | private int mNewX;
12 | private int mNewY;
13 |
14 | private int mDirection;
15 |
16 | public GameTile getCollisionTile() {
17 | return mCollisionTile;
18 | }
19 |
20 | public void setCollisionTile(GameTile collisionTile) {
21 | mCollisionTile = collisionTile;
22 | }
23 |
24 | public boolean isSolvable() {
25 | return mSolvable;
26 | }
27 |
28 | public void setSolvable(boolean solvable) {
29 | mSolvable = solvable;
30 | }
31 |
32 | public int getNewX() {
33 | return mNewX;
34 | }
35 |
36 | public void setNewX(int newX) {
37 | mNewX = newX;
38 | }
39 |
40 | public int getNewY() {
41 | return mNewY;
42 | }
43 |
44 | public void setNewY(int newY) {
45 | mNewY = newY;
46 | }
47 |
48 | public int getDirection() {
49 | return mDirection;
50 | }
51 |
52 | public void setDirection(int direction) {
53 | mDirection = direction;
54 | }
55 |
56 | public void solveCollision() {
57 | int tileX = mCollisionTile.getX();
58 | int tileY = mCollisionTile.getY();
59 | int width = mCollisionTile.getWidth();
60 | int height = mCollisionTile.getHeight();
61 |
62 | switch (mDirection) {
63 | case Player.DIRECTION_LEFT:
64 | case Player.DIRECTION_RIGHT:
65 | if (mNewY > tileY) {
66 | if (mNewY + SOLVE_LENGTH > tileY + height) {
67 | this.mSolvable = true;
68 | this.mNewY = tileY + height;
69 | } else {
70 | this.mSolvable = false;
71 | }
72 | } else {
73 | if (mNewY + height - SOLVE_LENGTH < tileY) {
74 | this.mSolvable = true;
75 | this.mNewY = tileY - height;
76 | } else {
77 | this.mSolvable = false;
78 | }
79 | }
80 | break;
81 | case Player.DIRECTION_UP:
82 | case Player.DIRECTION_DOWN:
83 | if (mNewX > tileX) {
84 | if (mNewX + SOLVE_LENGTH > tileX + width) {
85 | this.mSolvable = true;
86 | this.mNewX = tileX + width;
87 | } else {
88 | this.mSolvable = false;
89 | }
90 | } else {
91 | if (mNewX + width - SOLVE_LENGTH < tileX) {
92 | this.mSolvable = true;
93 | this.mNewX = tileX - width;
94 | } else {
95 | this.mSolvable = false;
96 | }
97 | }
98 | break;
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/ConnectionItem.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity;
2 |
3 | public class ConnectionItem {
4 | public String name;
5 | public String ip;
6 |
7 | public ConnectionItem(String name, String ip) {
8 | this.name = name;
9 | this.ip = ip;
10 | }
11 |
12 | @Override
13 | public int hashCode() {
14 | return 0;
15 | }
16 |
17 | @Override
18 | public boolean equals(Object o) {
19 | ConnectionItem other = (ConnectionItem) o;
20 | return this.ip.equals(other.ip);
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/DynamicImage.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Point;
5 | import android.util.Log;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * 动态图片类,为所有动态游戏对象基类
11 | */
12 | public class DynamicImage extends BaseImage {
13 |
14 | //是否循环播放
15 | public static boolean LOOP_PLAY = false;
16 | //动画播放间隙时间
17 | private static final int ANIM_TIME = 100;
18 |
19 | //上一帧播放时间
20 | private long mLastPlayTime = 0;
21 | //播放当前帧的ID
22 | private int mPlayID = 0;
23 | //动画frame数量
24 | private int mFrameCount = 0;
25 | //动画资源图片
26 | protected List mFrameBitmap = null;
27 | //是否循环播放
28 | private boolean mIsLoop = LOOP_PLAY;
29 | //是否结束播放结束
30 | private boolean mIsEnd = false;
31 |
32 | public DynamicImage() {
33 | }
34 |
35 | public DynamicImage(List frameBitmap, Point point) {
36 | super(frameBitmap.get(0), point);
37 | this.mFrameBitmap = frameBitmap;
38 | this.mFrameCount = frameBitmap.size();
39 | }
40 |
41 | public DynamicImage(List frameBitmap, boolean isLoop, Point point) {
42 | this(frameBitmap, point);
43 | this.mIsLoop = isLoop;
44 | }
45 |
46 | public DynamicImage(Bitmap baseImage, List frameBitmap, Point point) {
47 | super(baseImage, point);
48 | setFrameBitmap(frameBitmap);
49 | }
50 |
51 | public DynamicImage(Bitmap baseImage, List frameBitmap, boolean isLoop, Point point) {
52 | this(baseImage, frameBitmap, point);
53 | this.mIsLoop = isLoop;
54 | }
55 |
56 | public List getFrameBitmap() {
57 | return mFrameBitmap;
58 | }
59 |
60 | public void setFrameBitmap(List frameBitmap) {
61 | if (frameBitmap != null) {
62 | mFrameBitmap = frameBitmap;
63 | mFrameCount = frameBitmap.size();
64 | }
65 | }
66 |
67 | public void doAnimation() {
68 | if (mFrameBitmap == null) {
69 | return;
70 | }
71 |
72 | //如果没有播放结束则继续播放
73 | if (!mIsEnd) {
74 | //设置当前游戏图片
75 | mBitmap = mFrameBitmap.get(mPlayID);
76 | long time = System.currentTimeMillis();
77 | if (time - mLastPlayTime > ANIM_TIME) {
78 | mPlayID++;
79 | mLastPlayTime = time;
80 | if (mPlayID >= mFrameCount) {
81 | //标志动画播放结束
82 | mIsEnd = true;
83 | if (mIsLoop) {
84 | //设置循环播放
85 | mIsEnd = false;
86 | mPlayID = 0;
87 | }
88 | }
89 | }
90 | }
91 | }
92 |
93 | public boolean isEnd() {
94 | return mIsEnd;
95 | }
96 |
97 | public void setLoop(boolean isLoop) {
98 | mIsLoop = isLoop;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/GameTile.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Point;
5 | import android.graphics.Rect;
6 |
7 | import com.kuoruan.bomberman.util.SceneManager;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * 地图单元对象
13 | */
14 | public class GameTile extends DynamicImage {
15 | //空白
16 | public static final int TYPE_EMPTY = 0;
17 | //外岩
18 | public static final int TYPE_OBSTACLE = 1;
19 | //岩石
20 | public static final int TYPE_ROCK = 2;
21 | //箱子
22 | public static final int TYPE_CRATES = 3;
23 | //炸弹
24 | public static final int TYPE_BOMB = 4;
25 | //炸弹火焰
26 | public static final int TYPE_BOMB_FIRE = 5;
27 | //道具
28 | public static final int TYPE_GIFT = 6;
29 |
30 | private int mType = TYPE_EMPTY;
31 | private boolean mVisible = true;
32 | private Rect mCollisionRect = null;
33 | private boolean mIsDynamic = false;
34 |
35 | public GameTile() {
36 | }
37 |
38 | public GameTile(List frameBitmap, int type) {
39 | this.mType = type;
40 | setFrameBitmap(frameBitmap);
41 | }
42 |
43 | public GameTile(Bitmap bitmap, Point point, int type) {
44 | this.mType = type;
45 | setBitmap(bitmap);
46 | setPoint(point);
47 | }
48 |
49 | public GameTile(List frameBitmap, Point point, int type) {
50 | super(frameBitmap, point);
51 | this.mIsDynamic = true;
52 | this.mType = type;
53 | }
54 |
55 | public GameTile(Bitmap baseBitmap, List frameBitmap, Point point, int type) {
56 | super(baseBitmap, frameBitmap, point);
57 | this.mIsDynamic = true;
58 | this.mType = type;
59 | }
60 |
61 | public GameTile(List frameBitmap, boolean isLoop, Point point, int type) {
62 | super(frameBitmap, isLoop, point);
63 | this.mIsDynamic = true;
64 | this.mType = type;
65 | }
66 |
67 | public GameTile(Bitmap baseBitmap, List frameBitmap, boolean isLoop, Point point, int type) {
68 | super(baseBitmap, frameBitmap, isLoop, point);
69 | this.mIsDynamic = true;
70 | this.mType = type;
71 | }
72 |
73 | public boolean isCollision(float x, float y, int width, int height) {
74 | if (this.mCollisionRect == null) {
75 | this.mCollisionRect = new Rect((int) x, (int) y, ((int) x + width), ((int) y + height));
76 | } else {
77 | this.mCollisionRect.set((int) x, (int) y, ((int) x + width), ((int) y + height));
78 | }
79 |
80 | return (this.mCollisionRect.intersects(mPoint.x, mPoint.y, (mPoint.x + getWidth()), (mPoint.y + getHeight())));
81 | }
82 |
83 | public int getType() {
84 | return mType;
85 | }
86 |
87 | public void setType(int type) {
88 | this.mType = type;
89 | }
90 |
91 | public boolean isVisible() {
92 | return this.mVisible;
93 | }
94 |
95 | public void setVisible(boolean visible) {
96 | this.mVisible = visible;
97 | }
98 |
99 | public boolean isDynamic() {
100 | return mIsDynamic;
101 | }
102 |
103 | public void setDynamic(boolean dynamic) {
104 | mIsDynamic = dynamic;
105 | }
106 |
107 | /**
108 | * 是否是物理冲撞块
109 | *
110 | * @return
111 | */
112 | public boolean isCollisionTile() {
113 | return ((this.mType != GameTile.TYPE_EMPTY) && this.mVisible);
114 | }
115 |
116 | public boolean isBlockerTile() {
117 | return (this.mType != GameTile.TYPE_EMPTY);
118 | }
119 |
120 | public void setMapPoint(int x, int y) {
121 | mPoint.x = x * SceneManager.tileWidth;
122 | mPoint.y = y * SceneManager.tileHeight;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/GameUi.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Point;
5 |
6 | /**
7 | * 游戏控制按钮
8 | */
9 | public class GameUi extends BaseImage {
10 |
11 | //按钮状态
12 | public static final int STATE_NORMAL = 1;
13 | public static final int STATE_INACTIVE = 2;
14 | public static final int STATE_ACTIVE = 3;
15 | public static final int STATE_READY = 4;
16 |
17 | private int mState = STATE_NORMAL;
18 |
19 | public GameUi(Bitmap bitmap){
20 | super(bitmap);
21 | }
22 |
23 | public int getState() {
24 | return mState;
25 | }
26 |
27 | public void setState(int state) {
28 | this.mState = state;
29 | }
30 |
31 | public void setStateReady() {
32 | this.mState = STATE_READY;
33 | }
34 |
35 | public boolean isStateNormal() {
36 | return (this.mState == STATE_NORMAL);
37 | }
38 |
39 | //判断点是否在当前对象中
40 | public boolean getImpact(int x, int y) {
41 | if ((x >= mPoint.x) && (x <= (mPoint.x + mWidth))) {
42 | if ((y >= mPoint.y) && (y <= (mPoint.y + mWidth))) {
43 | return true;
44 | }
45 | }
46 |
47 | return false;
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/Player.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Point;
5 | import android.util.Log;
6 |
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | /**
11 | * 玩家角色
12 | */
13 | public class Player extends DynamicImage {
14 |
15 | private static final String TAG = "Player";
16 |
17 | //角色状态
18 | public static final int STATE_MOVING = 1;
19 | public static final int STATE_STOP = 2;
20 | public static final int STATE_DIE = 3;
21 | //默认移动速度
22 | public static final int DEFAULT_SPEED = 3;
23 | //角色移动方向
24 | public static final int DIRECTION_UP = 1;
25 | public static final int DIRECTION_DOWN = 2;
26 | public static final int DIRECTION_LEFT = 3;
27 | public static final int DIRECTION_RIGHT = 4;
28 | //角色死亡
29 | public static final int PLAYER_DIE = 5;
30 |
31 | private int id = 0;
32 | //角色状态
33 | private int mState = 0;
34 | //角色移动速度
35 | private int mSpeed = DEFAULT_SPEED;
36 | //当前分数
37 | private int mScore = 0;
38 | //水平方向
39 | private int mDirection = 0;
40 | //上次移动方向
41 | private int mPreDirection = 0;
42 | //各个方向的图片
43 | private Map> mFrameBitmaps;
44 |
45 | public Player(Bitmap bitmap, Map> frameBitmaps, Point point) {
46 | super(bitmap, null, true, point);
47 | this.mFrameBitmaps = frameBitmaps;
48 | }
49 |
50 | public int getId() {
51 | return id;
52 | }
53 |
54 | public void setId(int id) {
55 | this.id = id;
56 | }
57 |
58 | public void addSpeed() {
59 | this.mSpeed++;
60 | }
61 |
62 | public int getSpeed() {
63 | return this.mSpeed;
64 | }
65 |
66 | public void addScore(int score) {
67 | this.mScore += score;
68 | }
69 |
70 | public int getScore() {
71 | return this.mScore;
72 | }
73 |
74 | public int getDirection() {
75 | return mDirection;
76 | }
77 |
78 | public void setDirection(int direction) {
79 | this.mDirection = direction;
80 | }
81 |
82 | public int getState() {
83 | return mState;
84 | }
85 |
86 | public void setState(int state) {
87 | this.mState = state;
88 | }
89 |
90 | public boolean isMoving() {
91 | return (this.mState == STATE_MOVING);
92 | }
93 |
94 | public boolean isAlive() {
95 | return (this.mState != STATE_DIE);
96 | }
97 |
98 | @Override
99 | public void doAnimation() {
100 | if (mDirection != 0 && mDirection != mPreDirection) {
101 | setFrameBitmap(mFrameBitmaps.get(mDirection));
102 | mPreDirection = mDirection;
103 | }
104 |
105 | if (mState == STATE_DIE) {
106 | setFrameBitmap(mFrameBitmaps.get(PLAYER_DIE));
107 | setLoop(false);
108 | }
109 |
110 | super.doAnimation();
111 | }
112 |
113 | //获取左上角的标准位置
114 | public Point getStandardPoint() {
115 | Point point = getStandardMapPoint(); //获取标准点
116 | point.x *= mWidth; //乘以宽高
117 | point.y *= mHeight;
118 | return point;
119 | }
120 |
121 | //获取当前玩家的标准二维点
122 | public Point getStandardMapPoint() {
123 | int nowX = getX();
124 | int nowY = getY();
125 |
126 | Point mapPoint = new Point();
127 |
128 | if (nowX != 0) {
129 | mapPoint.x = (int) ((float) nowX / mWidth + .5);
130 |
131 | }
132 | if (nowY != 0) {
133 | mapPoint.y = (int) ((float) nowY / mHeight + .5);
134 | }
135 |
136 | return mapPoint;
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/data/GameData.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity.data;
2 |
3 | /**
4 | * 游戏地图单元对象,获取自数据库
5 | */
6 |
7 | public class GameData {
8 |
9 | private int id;
10 | private int mType;
11 | private int mSubType;
12 | private int mDrawable;
13 | private boolean mIsVisible = true;
14 |
15 | public GameData() {
16 | }
17 |
18 | public int getId() {
19 | return id;
20 | }
21 |
22 | public void setId(int id) {
23 | this.id = id;
24 | }
25 |
26 | public int getType() {
27 | return mType;
28 | }
29 |
30 | public void setType(int type) {
31 | mType = type;
32 | }
33 |
34 | public int getSubType() {
35 | return mSubType;
36 | }
37 |
38 | public void setSubType(int subType) {
39 | mSubType = subType;
40 | }
41 |
42 | public int getDrawable() {
43 | return mDrawable;
44 | }
45 |
46 | public void setDrawable(int drawable) {
47 | mDrawable = drawable;
48 | }
49 |
50 | public boolean isVisible() {
51 | return mIsVisible;
52 | }
53 |
54 | public void setVisible(boolean visible) {
55 | mIsVisible = visible;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/entity/data/GameLevelData.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.entity.data;
2 |
3 | import java.util.Arrays;
4 |
5 | /**
6 | * 游戏关卡相关数据
7 | */
8 |
9 | public class GameLevelData {
10 | private int id;
11 | private int stage;
12 | private String LevelTiles;
13 | private int playerStartX;
14 | private int playerStartY;
15 |
16 | public GameLevelData() {
17 | }
18 |
19 | public int getId() {
20 | return id;
21 | }
22 |
23 | public void setId(int id) {
24 | this.id = id;
25 | }
26 |
27 | public int getStage() {
28 | return stage;
29 | }
30 |
31 | public void setStage(int stage) {
32 | this.stage = stage;
33 | }
34 |
35 | public String getLevelTiles() {
36 | return LevelTiles;
37 | }
38 |
39 | public void setLevelTiles(String levelTiles) {
40 | LevelTiles = levelTiles;
41 | }
42 |
43 | public int getPlayerStartX() {
44 | return playerStartX;
45 | }
46 |
47 | public void setPlayerStartX(int playerStartX) {
48 | this.playerStartX = playerStartX;
49 | }
50 |
51 | public int getPlayerStartY() {
52 | return playerStartY;
53 | }
54 |
55 | public void setPlayerStartY(int playerStartY) {
56 | this.playerStartY = playerStartY;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/net/ConnectedService.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.net;
2 |
3 | import android.os.Bundle;
4 | import android.os.Handler;
5 | import android.os.HandlerThread;
6 | import android.os.Looper;
7 | import android.os.Message;
8 | import android.util.Log;
9 |
10 | import com.kuoruan.bomberman.util.ConnectConstants;
11 | import com.kuoruan.bomberman.util.DataUtil;
12 | import com.kuoruan.bomberman.util.GameConstants;
13 |
14 | import org.json.JSONException;
15 | import org.json.JSONObject;
16 |
17 | import java.io.BufferedReader;
18 | import java.io.IOException;
19 | import java.io.InputStream;
20 | import java.io.InputStreamReader;
21 | import java.io.OutputStream;
22 | import java.net.InetSocketAddress;
23 | import java.net.ServerSocket;
24 | import java.net.Socket;
25 |
26 | /**
27 | * 联机后数据传输
28 | */
29 | public class ConnectedService {
30 |
31 | public static final String TAG = "ConnectedService";
32 | private static final boolean DEBUG = true;
33 |
34 | private String mIp;
35 |
36 | private Socket mSocket;
37 | private GameReceiver mReceiver;
38 | private GameSender mSender;
39 | private boolean isServer;
40 |
41 | private static final int TCP_PORT = 8899;
42 |
43 | private Handler mRequestHandler;
44 |
45 | public ConnectedService(Handler handler, String ip, boolean isServer) {
46 | mRequestHandler = handler;
47 | this.isServer = isServer;
48 | this.mIp = ip;
49 | mReceiver = new GameReceiver();
50 | mReceiver.start();
51 |
52 | HandlerThread sendThread = new HandlerThread("GameSender");
53 | sendThread.start();
54 | mSender = new GameSender(sendThread.getLooper());
55 | }
56 |
57 | public void stop() {
58 | mSender.quit();
59 | mReceiver.quit();
60 | }
61 |
62 | /**
63 | * 发送TCP数据
64 | *
65 | * @param jsonObject
66 | */
67 | public void sendTCPData(JSONObject jsonObject) {
68 | byte[] data = DataUtil.JSONToTCPBytes(jsonObject);
69 | Message msg = Message.obtain();
70 | msg.obj = data;
71 | mSender.sendMessage(msg);
72 | }
73 |
74 | /**
75 | * TCP消息接收线程
76 | */
77 | class GameReceiver extends Thread {
78 |
79 | //byte[] buf = new byte[1024];
80 | boolean isRunning = true;
81 |
82 | ServerSocket server;
83 | InputStream is;
84 | BufferedReader buf;
85 |
86 | public GameReceiver() {
87 | }
88 |
89 | @Override
90 | public void run() {
91 | try {
92 | if (isServer) {
93 | Log.i(TAG, "Connected: it is server");
94 | server = new ServerSocket(TCP_PORT);
95 | mSocket = server.accept();
96 | Log.d(TAG, "server:net connected");
97 | mRequestHandler.sendEmptyMessage(ConnectConstants.GAME_CONNECTED);
98 | } else {
99 | Log.i(TAG, "Connected: it is client");
100 | Socket s = new Socket();
101 | InetSocketAddress address = new InetSocketAddress(mIp, TCP_PORT);
102 | /*
103 | * 连接失败尝试重连,重试8次 因为机器性能不一样不能保证作为Server端的Activity先于客户端启动
104 | */
105 | int retryCount = 0;
106 | while (retryCount < 8) {
107 | try {
108 | s.connect(address);
109 | mSocket = s;
110 | mRequestHandler.sendEmptyMessage(ConnectConstants.GAME_CONNECTED);
111 | Log.d(TAG, "client:net connected");
112 | break;
113 | } catch (IOException e) {
114 | retryCount++;
115 | s = new Socket();
116 | try {
117 | Thread.sleep(200);
118 | } catch (InterruptedException e1) {
119 | Log.d(TAG, "thread exception : " + e1.getMessage());
120 | }
121 | Log.d(TAG, "connect exception :" + e.getMessage() + " retry count=" + retryCount);
122 | }
123 | }
124 | if (retryCount >= 8) {
125 | return;
126 | }
127 | }
128 | } catch (IOException e) {
129 | Log.d(TAG, "socket exception:" + e.getMessage());
130 | return;
131 | }
132 |
133 | try {
134 | is = mSocket.getInputStream();
135 | buf = new BufferedReader(new InputStreamReader(is));
136 | String data;
137 | while (isRunning) {
138 | if ((data = buf.readLine()) == null) {
139 | // 连接断开
140 | break;
141 | }
142 | if (DEBUG) {
143 | Log.d(TAG, "tcp received:" + data);
144 | }
145 | processNetData(data);
146 | }
147 | } catch (IOException e) {
148 | Log.d(TAG, "IOException: an error occurs while receiving data");
149 | }
150 | }
151 |
152 | public void quit() {
153 | try {
154 | isRunning = false;
155 | if (is != null) {
156 | is.close();
157 | }
158 | if (buf != null) {
159 | buf.close();
160 | }
161 | if (mSocket != null) {
162 | mSocket.close();
163 | }
164 | if (server != null) {
165 | server.close();
166 | }
167 | } catch (IOException e) {
168 | Log.d(TAG, "close Socket Exception:" + e.getMessage());
169 | }
170 | }
171 |
172 | }
173 |
174 | /**
175 | * 把消息交给TCP发送线程发送
176 | */
177 | class GameSender extends Handler {
178 |
179 | public GameSender(Looper looper) {
180 | super(looper);
181 | }
182 |
183 | @Override
184 | public void handleMessage(Message msg) {
185 | byte[] data = (byte[]) msg.obj;
186 | try {
187 | if (mSocket == null) {
188 | Log.d(TAG, "Send fail,socket is null");
189 | return;
190 | }
191 | OutputStream os = mSocket.getOutputStream();
192 | // 发送数据
193 | os.write(data);
194 | os.flush();
195 | } catch (IOException e) {
196 | Log.d(TAG, "tcp socket error:" + e.getMessage());
197 | }
198 |
199 | }
200 |
201 | public void quit() {
202 | getLooper().quit();
203 | }
204 |
205 | }
206 |
207 | // 处理消息
208 | private void processNetData(String data) {
209 | JSONObject jsonObject = null;
210 | int type = 0;
211 | try {
212 | jsonObject = new JSONObject(data);
213 | type = jsonObject.getInt(ConnectConstants.TYPE);
214 | } catch (JSONException e) {
215 | e.printStackTrace();
216 | }
217 |
218 | switch (type) {
219 | case GameConstants.PLAYER_ADD:
220 | case GameConstants.PLAYER_MOVE:
221 | case GameConstants.PLAYER_STOP:
222 | case GameConstants.PLAYER_DIE:
223 | case GameConstants.SET_BOMB:
224 | notifyPlayerAction(type, jsonObject);
225 | break;
226 | default:
227 | break;
228 | }
229 | }
230 |
231 | private void notifyPlayerAction(int type, JSONObject jsonObject) {
232 | if (jsonObject == null) {
233 | return;
234 | }
235 | Message msg = Message.obtain();
236 | msg.what = type;
237 | msg.obj = jsonObject;
238 | mRequestHandler.sendMessage(msg);
239 | }
240 |
241 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/net/ConnectingService.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.net;
2 |
3 | import android.os.Build;
4 | import android.os.Bundle;
5 | import android.os.Handler;
6 | import android.os.HandlerThread;
7 | import android.os.Looper;
8 | import android.os.Message;
9 | import android.util.Log;
10 |
11 | import com.kuoruan.bomberman.util.ConnectConstants;
12 |
13 | import org.json.JSONException;
14 | import org.json.JSONObject;
15 |
16 | import java.io.IOException;
17 | import java.io.OutputStream;
18 | import java.net.DatagramPacket;
19 | import java.net.DatagramSocket;
20 | import java.net.InetAddress;
21 | import java.net.MulticastSocket;
22 | import java.net.Socket;
23 | import java.net.SocketException;
24 | import java.net.UnknownHostException;
25 | import java.util.Arrays;
26 |
27 | /**
28 | * UDP联机管理
29 | * 初始化这个对象后,调用{@link #start()}方法就会搜索局域网 内的可连接手机,同时自己也会成为别人可见的对象。
30 | * 当搜索到可联机对象后会返回可连对象的机器名和IP地址。
31 | */
32 | public class ConnectingService {
33 | public static final String TAG = "ConnectManager";
34 | private static final boolean DEBUG = true;
35 |
36 | private String mIp;
37 |
38 | // UPD接收程序
39 | private DatagramSocket mDataSocket;
40 | // 点对多广播
41 | private MulticastSocket mMulticastSocket;
42 | private InetAddress mCastAddress;
43 |
44 | // 广播组地址
45 | private static final String MUL_IP = "230.0.2.2";
46 | //多人游戏端口
47 | private static final int MUL_PORT = 1688;
48 | //UDP端口
49 | private static final int UDP_PORT = 2599;
50 |
51 | // 接收UPD消息
52 | private UDPReceiver mUDPReceiver;
53 | // 接收广播消息
54 | private MulticastReceiver mMulticastReceiver;
55 | // udp消息发送模块
56 | private UDPSendHandler mUDPSender;
57 | // 广播消息发送模块
58 | private MulticastSendHandler mBroadcastSender;
59 |
60 | private Handler mRequestHandler;
61 |
62 | public ConnectingService(String ip, Handler request) {
63 | this.mRequestHandler = request;
64 | this.mIp = ip;
65 | this.mUDPReceiver = new UDPReceiver();
66 | this.mMulticastReceiver = new MulticastReceiver();
67 | }
68 |
69 | /**
70 | * 启动连接程序
71 | */
72 | public void start() {
73 | mUDPReceiver.start();
74 | mMulticastReceiver.start();
75 |
76 | HandlerThread udpThread = new HandlerThread("udpSender");
77 | udpThread.start();
78 | mUDPSender = new UDPSendHandler(udpThread.getLooper());
79 |
80 | HandlerThread broadcastThread = new HandlerThread("broadcastSender");
81 | broadcastThread.start();
82 | mBroadcastSender = new MulticastSendHandler(broadcastThread.getLooper());
83 | }
84 |
85 | public void stop() {
86 | mUDPReceiver.quit();
87 | mMulticastReceiver.quit();
88 | mUDPSender.getLooper().quit();
89 | mBroadcastSender.getLooper().quit();
90 | }
91 |
92 | /**
93 | * 发送一个查询广播消息,查询当前可连接对象
94 | */
95 | public void sendScanMsg() {
96 | Message msg = Message.obtain();
97 | byte[] buf = packageBroadcast(ConnectConstants.BROADCAST_JOIN);
98 | msg.obj = buf;
99 | mBroadcastSender.sendMessage(msg);
100 | }
101 |
102 | /**
103 | * 发送一个查询广播消息,退出可联机
104 | */
105 | public void sendExitMsg() {
106 | // 起一个线程发送一个局域网广播(android主线程不能有网络操作)
107 | // 不用mMultiCastSocket对象发送时因为退出的时候涉及跨线程操作
108 | // 可能mMultiCastSocket已经close状态,不可控
109 | new Thread() {
110 | @Override
111 | public void run() {
112 | MulticastSocket multicastSocket;
113 | try {
114 | InetAddress address = InetAddress.getByName(MUL_IP);
115 | multicastSocket = new MulticastSocket();
116 | multicastSocket.setTimeToLive(1);
117 | byte[] buf = packageBroadcast(ConnectConstants.BROADCAST_EXIT);
118 | DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
119 | // 接收地址和group的标识相同
120 | datagramPacket.setAddress(address);
121 | // 发送至的端口号
122 | datagramPacket.setPort(MUL_PORT);
123 | multicastSocket.send(datagramPacket);
124 | multicastSocket.close();
125 | } catch (IOException e) {
126 | Log.d(TAG, "send exit multiCast fail:" + e.getMessage());
127 | }
128 | }
129 | }.start();
130 | }
131 |
132 | /**
133 | * 发送请求连接消息
134 | *
135 | * @param ipDst
136 | */
137 | public void sendAskConnect(String ipDst) {
138 | Message msg = Message.obtain();
139 | Bundle b = new Bundle();
140 | b.putString("ipDst", ipDst);
141 | byte[] data = createAskConnect();
142 | b.putByteArray("data", data);
143 | msg.setData(b);
144 | mUDPSender.sendMessage(msg);
145 | }
146 |
147 |
148 | /**
149 | * 同意联机
150 | */
151 | public void accept(String ipDst) {
152 | Message msg = Message.obtain();
153 | Bundle b = new Bundle();
154 | b.putString("ipDst", ipDst);
155 | byte[] data = createConnectResponse(ConnectConstants.CONNECT_AGREE);
156 | b.putByteArray("data", data);
157 | msg.setData(b);
158 | mUDPSender.sendMessage(msg);
159 | }
160 |
161 | /**
162 | * 拒绝请求
163 | */
164 | public void reject(String ipDst) {
165 | Message msg = Message.obtain();
166 | Bundle b = new Bundle();
167 | b.putString("ipDst", ipDst);
168 | byte[] data = createConnectResponse(ConnectConstants.CONNECT_REJECT);
169 | b.putByteArray("data", data);
170 | msg.setData(b);
171 | mUDPSender.sendMessage(msg);
172 | }
173 |
174 | /**
175 | * 接收UDP消息,未建立TCP连接之前,都通过udp接收消息
176 | *
177 | * @author qingc
178 | */
179 | class UDPReceiver extends Thread {
180 |
181 | byte[] buf = new byte[1024];
182 | boolean isRunning = true;
183 |
184 | private DatagramSocket dataSocket;
185 | private DatagramPacket dataPacket;
186 |
187 | public UDPReceiver() {
188 | try {
189 | dataSocket = new DatagramSocket(UDP_PORT);
190 | mDataSocket = dataSocket;
191 | dataPacket = new DatagramPacket(buf, buf.length);
192 | } catch (SocketException e) {
193 | isRunning = false;
194 | Log.d(TAG, "Socket Exception:" + e.getMessage());
195 | }
196 | }
197 |
198 | @Override
199 | public void run() {
200 | try {
201 | while (isRunning) {
202 | mDataSocket.receive(dataPacket);
203 | String data = new String(dataPacket.getData(), 0, dataPacket.getLength());
204 | Log.d(TAG, "udp receiver: " + data);
205 | processUDPReceive(data);
206 | }
207 | } catch (SocketException e) {
208 | isRunning = false;
209 | Log.d(TAG, "Socket Exception:" + e.getMessage());
210 | } catch (IOException e) {
211 | isRunning = false;
212 | Log.d(TAG, "IOException: an error occurs while receiving the packet");
213 | }
214 | }
215 |
216 | public void quit() {
217 | dataSocket.close();
218 | isRunning = false;
219 | }
220 |
221 | }
222 |
223 | /**
224 | * 处理UDP接受数据
225 | *
226 | * @param data 接收到的Json字符串
227 | */
228 | private void processUDPReceive(String data) {
229 | JSONObject jsonObject = null;
230 | int type = 0;
231 | try {
232 | jsonObject = new JSONObject(data);
233 | type = jsonObject.getInt(ConnectConstants.TYPE);
234 | } catch (JSONException e) {
235 | e.printStackTrace();
236 | }
237 |
238 | switch (type) {
239 | case ConnectConstants.UDP_JOIN:
240 | processUDPJoin(jsonObject);
241 | break;
242 | case ConnectConstants.CONNECT_ASK:
243 | processConnectAsk(jsonObject);
244 | break;
245 | case ConnectConstants.CONNECT_AGREE:
246 | case ConnectConstants.CONNECT_REJECT:
247 | processConnectResponse(jsonObject);
248 | default:
249 | break;
250 | }
251 | }
252 |
253 | /**
254 | * 发送UDP消息,未建立TCP连接之前,都通过UDP发送指令到制定的ip
255 | */
256 | class UDPSendHandler extends Handler {
257 |
258 | public UDPSendHandler(Looper looper) {
259 | super(looper);
260 | }
261 |
262 | @Override
263 | public void handleMessage(Message msg) {
264 | Bundle b = msg.peekData();
265 | String ipDst = b.getString("ipDst");
266 | byte[] data = b.getByteArray("data");
267 | Log.d(TAG, "udp send destination ip:" + ipDst);
268 | if (DEBUG) {
269 | Log.d(TAG, "udp send data:" + Arrays.toString(data));
270 | }
271 | if (data == null) {
272 | onError(ConnectConstants.UDP_DATA_ERROR);
273 | }
274 | try {
275 | DatagramSocket ds;
276 | ds = mDataSocket;
277 | if (ds == null) {
278 | onError(ConnectConstants.SOCKET_NULL);
279 | return;
280 | }
281 | InetAddress dstAddress = InetAddress.getByName(ipDst);
282 |
283 | // 创建发送数据包
284 | DatagramPacket dataPacket = new DatagramPacket(data, data.length, dstAddress, UDP_PORT);
285 | ds.send(dataPacket);
286 | } catch (UnknownHostException e1) {
287 | Log.d(TAG, "ip is not corrected");
288 | onError(ConnectConstants.UDP_IP_ERROR);
289 | } catch (IOException e) {
290 | Log.d(TAG, "udp socket error:" + e.getMessage());
291 | }
292 |
293 | }
294 |
295 | public void quit() {
296 | getLooper().quit();
297 | }
298 |
299 | }
300 |
301 | /**
302 | * 接收广播消息线程,监听其他手机的扫描或加入广播
303 | */
304 | class MulticastReceiver extends Thread {
305 |
306 | byte[] buffer = new byte[1024];
307 | private boolean isRunning = true;
308 |
309 | private MulticastSocket multiSocket;
310 | private DatagramPacket dataPacket;
311 |
312 | public MulticastReceiver() {
313 | try {
314 | InetAddress address = InetAddress.getByName(MUL_IP);
315 | multiSocket = new MulticastSocket();
316 | // 接收数据时需要指定监听的端口号
317 | multiSocket = new MulticastSocket(MUL_PORT);
318 | // 加入广播组
319 | mCastAddress = address;
320 | multiSocket.joinGroup(address);
321 | multiSocket.setTimeToLive(1);
322 | dataPacket = new DatagramPacket(buffer, buffer.length);
323 | // 全局引用指向这里的广播socket,用于发送广播消息
324 | mMulticastSocket = multiSocket;
325 | } catch (IOException e) {
326 | isRunning = false;
327 | Log.d(TAG, "Init multiCast fail by IOException=" + e.getMessage());
328 | }
329 | }
330 |
331 | @Override
332 | public void run() {
333 | try {
334 | while (isRunning) {
335 | // 接收数据,会进入阻塞状态
336 | mMulticastSocket.receive(dataPacket);
337 | // 从buffer中截取收到的数据
338 | byte[] message = new byte[dataPacket.getLength()];
339 | System.arraycopy(buffer, 0, message, 0,
340 | dataPacket.getLength());
341 | Log.d(TAG, "multiCast receive:" + Arrays.toString(message));
342 | String ip = processBroadcast(message);
343 | // Check ip address and send ip address myself to it.
344 | if (ip != null && !ip.equals(mIp)) {
345 | Message msg = Message.obtain();
346 | Bundle b = new Bundle();
347 | b.putString("ipDst", ip);
348 | byte[] data = packageUDPJoin();
349 | b.putByteArray("data", data);
350 | msg.setData(b);
351 | mUDPSender.sendMessage(msg);
352 | }
353 | }
354 | } catch (IOException e) {
355 | Log.d(TAG, "IOException=" + e.getMessage());
356 | }
357 | }
358 |
359 | public void quit() {
360 | // close socket
361 | multiSocket.close();
362 | isRunning = false;
363 | }
364 |
365 | }
366 |
367 | /**
368 | * 发送广播消息
369 | */
370 | class MulticastSendHandler extends Handler {
371 |
372 | public MulticastSendHandler(Looper looper) {
373 | super(looper);
374 | }
375 |
376 | @Override
377 | public void handleMessage(Message msg) {
378 |
379 | byte[] buf = (byte[]) msg.obj;
380 | if (DEBUG) {
381 | Log.d(TAG, "BroadcastSendHandler:data=" + buf);
382 | }
383 | MulticastSocket s = mMulticastSocket;
384 | if (s == null) {
385 | onError(ConnectConstants.SOCKET_NULL);
386 | return;
387 | }
388 | InetAddress address = mCastAddress;
389 | if (address == null || !address.isMulticastAddress()) {
390 | onError(ConnectConstants.MULTICAST_ERROR);
391 | return;
392 | }
393 | try {
394 | // s.setTimeToLive(1); is it nessary?
395 | DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
396 | // 设置发送group地址
397 | datagramPacket.setAddress(address);
398 | // 发送至的端口号
399 | datagramPacket.setPort(MUL_PORT);
400 | s.send(datagramPacket);
401 | } catch (IOException e) {
402 | Log.d(TAG, "send multicast fail:" + e.getMessage());
403 | onError(ConnectConstants.SOCKET_NULL);
404 | }
405 | }
406 |
407 | public void quit() {
408 | getLooper().quit();
409 | }
410 | }
411 |
412 | /**
413 | * 错误信息
414 | *
415 | * @param error
416 | */
417 | private void onError(int error) {
418 | Log.d(TAG, "error:" + error);
419 | Message msg = Message.obtain();
420 | msg.what = error;
421 | mRequestHandler.sendMessage(msg);
422 | }
423 |
424 | /**
425 | * 有新的可联机对象加入
426 | *
427 | * @param name 机器名
428 | * @param ip 地址
429 | */
430 | private void onJoin(String name, String ip) {
431 | Message msg = Message.obtain();
432 | msg.what = ConnectConstants.ON_JOIN;
433 | Bundle b = new Bundle();
434 | b.putString("name", name);
435 | b.putString("ip", ip);
436 | msg.setData(b);
437 | mRequestHandler.sendMessage(msg);
438 | }
439 |
440 | /**
441 | * 有可联机对象退出
442 | *
443 | * @param name 机器名
444 | * @param ip 地址
445 | */
446 | private void onExit(String name, String ip) {
447 | Message msg = Message.obtain();
448 | msg.what = ConnectConstants.ON_EXIT;
449 | Bundle b = new Bundle();
450 | b.putString("name", name);
451 | b.putString("ip", ip);
452 | msg.setData(b);
453 | mRequestHandler.sendMessage(msg);
454 | }
455 |
456 | /**
457 | * 处理加入可连接对象消息
458 | *
459 | * @param jsonObject 接收到Json对象
460 | */
461 | private void processUDPJoin(JSONObject jsonObject) {
462 | String name = null;
463 | String ip = null;
464 | try {
465 | name = jsonObject.getString(ConnectConstants.HOST_NAME);
466 | ip = jsonObject.getString(ConnectConstants.IP);
467 | } catch (JSONException e) {
468 | e.printStackTrace();
469 | }
470 | //处理加入用户
471 | onJoin(name, ip);
472 | }
473 |
474 | /**
475 | * 将本机名称和ip地址封装成Json发送
476 | *
477 | * @return
478 | */
479 | private byte[] packageUDPJoin() {
480 | JSONObject jsonObject = new JSONObject();
481 | try {
482 | jsonObject.put(ConnectConstants.HOST_NAME, Build.BRAND + "-" + Build.MODEL);
483 | jsonObject.put(ConnectConstants.IP, mIp);
484 | } catch (JSONException e) {
485 | e.printStackTrace();
486 | }
487 | return jsonObject.toString().getBytes();
488 | }
489 |
490 | /**
491 | * 处理广播消息
492 | *
493 | * @param data 接收到的消息体
494 | * @return 返回解析到的ip地址
495 | */
496 | private String processBroadcast(byte[] data) {
497 | String json = new String(data);
498 | String ip = null;
499 | String name = null;
500 | int type = 0;
501 | try {
502 | JSONObject jsonObject = new JSONObject(json);
503 | ip = jsonObject.getString(ConnectConstants.IP);
504 | name = jsonObject.getString(ConnectConstants.HOST_NAME);
505 | type = jsonObject.getInt(ConnectConstants.TYPE);
506 | } catch (JSONException e) {
507 | e.printStackTrace();
508 | }
509 | Log.d(TAG, "processBroadcast-->" + "name=" + name + " ip=" + ip);
510 | // 如果是自己发送的信息,则不加入可连接集合
511 | if (mIp.equals(ip)) {
512 | return ip;
513 | }
514 | if (type == ConnectConstants.BROADCAST_JOIN) {
515 | onJoin(name, ip);
516 | } else if (type == ConnectConstants.BROADCAST_EXIT) {
517 | onExit(name, ip);
518 | }
519 | return ip;
520 | }
521 |
522 | /**
523 | * 将本机名称和ip地址封装成byte数组
524 | *
525 | * @return
526 | */
527 | private byte[] packageBroadcast(int type) {
528 | JSONObject jsonObject = new JSONObject();
529 | try {
530 | jsonObject.put(ConnectConstants.IP, mIp);
531 | jsonObject.put(ConnectConstants.HOST_NAME, Build.BRAND + "-" + Build.MODEL);
532 | jsonObject.put(ConnectConstants.TYPE, type);
533 | } catch (JSONException e) {
534 | e.printStackTrace();
535 | }
536 | return jsonObject.toString().getBytes();
537 | }
538 |
539 | /**
540 | * 封装请求连接消息体
541 | *
542 | * @return
543 | */
544 | private byte[] createAskConnect() {
545 | JSONObject jsonObject = new JSONObject();
546 | try {
547 | jsonObject.put(ConnectConstants.IP, mIp);
548 | jsonObject.put(ConnectConstants.HOST_NAME, Build.BRAND + "-" + Build.MODEL);
549 | jsonObject.put(ConnectConstants.TYPE, ConnectConstants.CONNECT_ASK);
550 | } catch (JSONException e) {
551 | e.printStackTrace();
552 | }
553 |
554 | return jsonObject.toString().getBytes();
555 | }
556 |
557 | /**
558 | * 解析请求联机数据
559 | *
560 | * @param jsonObject
561 | */
562 | private void processConnectAsk(JSONObject jsonObject) {
563 | String ip = null;
564 | String name = null;
565 | int type = 0;
566 |
567 | try {
568 | ip = jsonObject.getString(ConnectConstants.IP);
569 | name = jsonObject.getString(ConnectConstants.HOST_NAME);
570 | type = jsonObject.getInt(ConnectConstants.TYPE);
571 | } catch (JSONException e) {
572 | e.printStackTrace();
573 | }
574 |
575 | Log.d(TAG, "processUDPJoin-->" + "name=" + name + " ip=" + ip);
576 | Message msg = Message.obtain();
577 | msg.what = type;
578 | Bundle b = new Bundle();
579 | b.putString("name", name);
580 | b.putString("ip", ip);
581 | msg.setData(b);
582 | mRequestHandler.sendMessage(msg);
583 | }
584 |
585 | /**
586 | * 创建连接相应消息
587 | *
588 | * @param type
589 | * @return 消息数组
590 | */
591 | private byte[] createConnectResponse(int type) {
592 | JSONObject jsonObject = new JSONObject();
593 | try {
594 | jsonObject.put(ConnectConstants.IP, mIp);
595 | jsonObject.put(ConnectConstants.HOST_NAME, Build.BOARD);
596 | jsonObject.put(ConnectConstants.TYPE, type);
597 | } catch (JSONException e) {
598 | e.printStackTrace();
599 | }
600 |
601 | return jsonObject.toString().getBytes();
602 | }
603 |
604 | /**
605 | * 解析连接请求响应并处理
606 | *
607 | * @param jsonObject
608 | */
609 | private void processConnectResponse(JSONObject jsonObject) {
610 | String ip = null;
611 | String name = null;
612 | int type = 0;
613 | try {
614 | ip = jsonObject.getString(ConnectConstants.IP);
615 | name = jsonObject.getString(ConnectConstants.HOST_NAME);
616 | type = jsonObject.getInt(ConnectConstants.TYPE);
617 | } catch (JSONException e) {
618 | e.printStackTrace();
619 | }
620 |
621 | Log.d(TAG, "processConnectResponse-->" + "name=" + name + " ip=" + ip);
622 | Message msg = Message.obtain();
623 | msg.what = type;
624 | Bundle b = new Bundle();
625 | b.putString("name", name);
626 | b.putString("ip", ip);
627 | msg.setData(b);
628 | mRequestHandler.sendMessage(msg);
629 | }
630 |
631 | }
632 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/util/BitmapManager.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.util;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapFactory;
6 |
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 |
11 | /**
12 | * Created by Liao on 2016/5/5 0005.
13 | */
14 | public class BitmapManager {
15 |
16 | private static Map mBitmapMaps = new HashMap<>();
17 |
18 | public static Bitmap setAndGetBitmap(Context context, int resourceId) {
19 | if (!mBitmapMaps.containsKey(resourceId)) {
20 | BitmapFactory.Options opts = new BitmapFactory.Options();
21 | opts.inJustDecodeBounds = true;
22 | Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId);
23 |
24 | if (bitmap != null) {
25 | mBitmapMaps.put(resourceId, bitmap);
26 | }
27 | }
28 |
29 | return mBitmapMaps.get(resourceId);
30 | }
31 |
32 | public static Map getBitmapMaps() {
33 | return mBitmapMaps;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/util/ConnectConstants.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.util;
2 |
3 | public class ConnectConstants {
4 |
5 | public static final int SOCKET_NULL = 0;
6 | public static final int IP_NULL = 1;
7 | public static final int ON_JOIN = 2;
8 | public static final int ON_EXIT = 3;
9 | public static final int UDP_IP_ERROR = 4;
10 | public static final int UDP_DATA_ERROR = 5;
11 | public static final int MULTICAST_ERROR = 6;
12 |
13 | public static final int CONNECT_ASK = 11;
14 | public static final int CONNECT_AGREE = 12;
15 | public static final int CONNECT_REJECT = 13;
16 |
17 | public static final int BROADCAST_JOIN = 0;
18 | public static final int BROADCAST_EXIT = 1;
19 |
20 | public static final int UDP_JOIN = 0;
21 |
22 | public static final int GAME_CONNECTED = 11;
23 |
24 | public static final String HOST_NAME = "hostName";
25 | public static final String IP = "ip";
26 | public static final String TYPE = "type";
27 | public static final String PLAYER_ID = "playerId";
28 | public static final String POINT_X = "x";
29 | public static final String POINT_Y = "y";
30 | public static final String DIRECTION = "direction";
31 | public static final String MAP_X = "mapX";
32 | public static final String MAP_Y = "mapY";
33 | public static final String BOMB_TYPE = "bombType";
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/util/DataUtil.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.util;
2 |
3 | import android.os.Bundle;
4 |
5 | import org.json.JSONArray;
6 | import org.json.JSONException;
7 | import org.json.JSONObject;
8 |
9 | import java.io.ByteArrayOutputStream;
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 | import java.lang.reflect.Array;
13 | import java.util.Collection;
14 | import java.util.Map;
15 | import java.util.Set;
16 |
17 | /**
18 | * 各种数据工具类
19 | */
20 | public class DataUtil {
21 |
22 | public static String streamToString(InputStream is) {
23 | byte[] bytes = new byte[1024];
24 | int length = 0;
25 | ByteArrayOutputStream os = new ByteArrayOutputStream();
26 | try {
27 | while ((length = is.read(bytes)) != -1) {
28 | os.write(bytes, 0, length);
29 | }
30 | os.flush();
31 | String result = new String(os.toByteArray(), "UTF-8");
32 | return result;
33 | } catch (IOException e) {
34 | e.printStackTrace();
35 | }
36 | return "";
37 | }
38 |
39 | public static byte[] JSONToTCPBytes(JSONObject jsonObject) {
40 | String data = jsonObject.toString() + "\n";
41 | return data.getBytes();
42 | }
43 |
44 | public static JSONObject bundleToJSONObj(Bundle bundle) {
45 | JSONObject json = new JSONObject();
46 | Set keys = bundle.keySet();
47 | for (String key : keys) {
48 | try {
49 | // json.put(key, bundle.get(key)); see edit below
50 | json.put(key, wrap(bundle.get(key)));
51 | } catch (JSONException e) {
52 | e.printStackTrace();
53 | }
54 | }
55 |
56 | return json;
57 | }
58 |
59 | public static Object wrap(Object o) {
60 | if (o == null) {
61 | return JSONObject.NULL;
62 | }
63 | if (o instanceof JSONArray || o instanceof JSONObject) {
64 | return o;
65 | }
66 | if (o.equals(JSONObject.NULL)) {
67 | return o;
68 | }
69 | try {
70 | if (o instanceof Collection) {
71 | return new JSONArray((Collection) o);
72 | } else if (o.getClass().isArray()) {
73 | return toJSONArray(o);
74 | }
75 | if (o instanceof Map) {
76 | return new JSONObject((Map) o);
77 | }
78 | if (o instanceof Boolean ||
79 | o instanceof Byte ||
80 | o instanceof Character ||
81 | o instanceof Double ||
82 | o instanceof Float ||
83 | o instanceof Integer ||
84 | o instanceof Long ||
85 | o instanceof Short ||
86 | o instanceof String) {
87 | return o;
88 | }
89 | if (o.getClass().getPackage().getName().startsWith("java.")) {
90 | return o.toString();
91 | }
92 | } catch (Exception ignored) {
93 | }
94 | return null;
95 | }
96 |
97 | private static Object toJSONArray(Object array) throws JSONException {
98 | JSONArray result = new JSONArray();
99 | if (!array.getClass().isArray()) {
100 | throw new JSONException("Not a primitive array: " + array.getClass());
101 | }
102 | final int length = Array.getLength(array);
103 | for (int i = 0; i < length; ++i) {
104 | result.put(wrap(Array.get(array, i)));
105 | }
106 | return result;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/util/GameConstants.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.util;
2 |
3 | public class GameConstants {
4 |
5 | //多人游戏
6 | public static final int MULTI_PLAYER_STAGE = 0;
7 | /**
8 | * 默认炸弹数量
9 | */
10 | public static final int DEFAULT_BOMB_COUNT = 2;
11 | public static final int GAME_OVER = 0;
12 | public static final int PLAYER_ADD = 1;
13 | public static final int PLAYER_MOVE = 2;
14 | public static final int PLAYER_STOP = 3;
15 | public static final int PLAYER_DIE = 4;
16 | public static final int SET_BOMB = 5;
17 |
18 | public static final int MODE_SINGLE = 0;
19 | public static final int MODE_FIGHT = 1;
20 | public static final int MODE_NET = 2;
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/util/PlayerManager.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.util;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Point;
6 | import android.os.Handler;
7 | import android.os.Message;
8 |
9 | import com.kuoruan.bomberman.dao.GameDataDao;
10 | import com.kuoruan.bomberman.entity.Player;
11 | import com.kuoruan.bomberman.entity.data.GameData;
12 |
13 | import org.json.JSONException;
14 | import org.json.JSONObject;
15 |
16 | import java.util.ArrayList;
17 | import java.util.HashMap;
18 | import java.util.List;
19 | import java.util.Map;
20 |
21 | /**
22 | * Created by Window10 on 2016/5/3.
23 | */
24 | public class PlayerManager {
25 | private static final String TAG = "PlayerManager";
26 | public static int mId = 1;
27 | private GameDataDao mGameDataDao;
28 |
29 | private Map mPlayers = new HashMap<>();
30 | private Player mMyPlayer = null;
31 | private Map mPlayerData = null;
32 | private Map>> mPlayerTemplates = new HashMap<>();
33 | private static final Point[] positions = {new Point(1, 1), new Point(15, 11), new Point(1, 11), new Point(15, 1)};
34 |
35 | private Context mContext;
36 | private Handler mHandler;
37 |
38 | public PlayerManager(Context context, Handler handler, int id) {
39 | mContext = context;
40 | mHandler = handler;
41 | mId = id;
42 | mGameDataDao = GameDataDao.getInstance(context);
43 | mPlayerData = mGameDataDao.getPlayerData();
44 | prepareMyPlayer();
45 | }
46 |
47 | /**
48 | * 初始化玩家
49 | *
50 | * @return
51 | */
52 | public void prepareMyPlayer() {
53 | Point mapPoint = positions[mId];
54 | addPlayer(mId, mapPoint);
55 | mMyPlayer = mPlayers.get(mId);
56 | noticeMyPlayer();
57 | }
58 |
59 | /**
60 | * 添加一个新的玩家
61 | */
62 | public void addPlayer(int id, Point mapPoint) {
63 | Bitmap bitmap = getFirstBitmap(id);
64 | mapPoint.x *= bitmap.getWidth();
65 | mapPoint.y = bitmap.getHeight();
66 | Player player = new Player(bitmap, mPlayerTemplates.get(id), mapPoint);
67 | player.setId(id);
68 | mPlayers.put(id, player);
69 | }
70 |
71 | private Bitmap getFirstBitmap(int id) {
72 | Map> playerTemplate = setAndGetPlayerTemplates(id);
73 | return playerTemplate.get(Player.DIRECTION_DOWN).get(0);
74 | }
75 |
76 | /**
77 | * 准备玩家图片模板
78 | *
79 | * @param id
80 | */
81 | private Map> setAndGetPlayerTemplates(int id) {
82 | if (!mPlayerTemplates.containsKey(id)) {
83 | GameData data = mPlayerData.get(id);
84 |
85 | Bitmap baseBitmap = BitmapManager.setAndGetBitmap(mContext, data.getDrawable());
86 |
87 | int width = baseBitmap.getWidth() / 3;
88 | int height = baseBitmap.getHeight() / 7;
89 |
90 | Map> map = new HashMap<>();
91 | for (int y = 0; y < 4; y++) {
92 | List list = new ArrayList<>();
93 | for (int x = 0; x < 3; x++) {
94 | Bitmap newBitmap = Bitmap.createBitmap(baseBitmap, x * width, y * height, width, height);
95 | list.add(newBitmap);
96 | }
97 |
98 | map.put(y + 1, list);
99 | }
100 |
101 | List dieBitmaps = new ArrayList<>();
102 | for (int y = 4; y < 7; y++) {
103 | for (int x = 0; x < 3; x++) {
104 | Bitmap newBitmap = Bitmap.createBitmap(baseBitmap, x * width, y * height, width, height);
105 | dieBitmaps.add(newBitmap);
106 | }
107 | }
108 |
109 | map.put(Player.PLAYER_DIE, dieBitmaps);
110 | mPlayerTemplates.put(id, map);
111 | }
112 |
113 | return mPlayerTemplates.get(id);
114 | }
115 |
116 | public Map getPlayers() {
117 | return mPlayers;
118 | }
119 |
120 | public int getPlayerCount() {
121 | return mPlayers.size();
122 | }
123 |
124 | public void handlePlayerMove(JSONObject jsonObject) {
125 | int pid = 0;
126 | int direction = 0;
127 | int x = 0;
128 | int y = 0;
129 | try {
130 | pid = jsonObject.getInt(ConnectConstants.PLAYER_ID);
131 | direction = jsonObject.getInt(ConnectConstants.DIRECTION);
132 | x = jsonObject.getInt(ConnectConstants.POINT_X);
133 | y = jsonObject.getInt(ConnectConstants.POINT_Y);
134 | } catch (JSONException e) {
135 | e.printStackTrace();
136 | }
137 |
138 | Player netPlayer = mPlayers.get(pid);
139 | netPlayer.setX(x);
140 | netPlayer.setY(y);
141 | netPlayer.setDirection(direction);
142 | netPlayer.setState(Player.STATE_MOVING);
143 | }
144 |
145 | public Player getMyPlayer() {
146 | return mMyPlayer;
147 | }
148 |
149 | public void handlePlayerAdd(JSONObject jsonObject) {
150 | int pid = 0;
151 | int x = 0;
152 | int y = 0;
153 | try {
154 | pid = jsonObject.getInt(ConnectConstants.PLAYER_ID);
155 | x = jsonObject.getInt(ConnectConstants.POINT_X);
156 | y = jsonObject.getInt(ConnectConstants.POINT_Y);
157 | } catch (JSONException e) {
158 | e.printStackTrace();
159 | }
160 | if (mPlayers.containsKey(pid)) {
161 | return;
162 | }
163 |
164 | addPlayer(pid, new Point(x, y));
165 | }
166 |
167 | public void handlePlayerStop(JSONObject jsonObject) {
168 | int pid = 0;
169 | try {
170 | pid = jsonObject.getInt(ConnectConstants.PLAYER_ID);
171 | } catch (JSONException e) {
172 | e.printStackTrace();
173 | }
174 | if (pid == mId) {
175 | return;
176 | }
177 | Player netPlayer = mPlayers.get(pid);
178 | netPlayer.setState(Player.STATE_STOP);
179 | netPlayer.setDirection(0);
180 | }
181 |
182 | public void handlePlayerDie(JSONObject jsonObject) {
183 | int pid = 0;
184 | try {
185 | pid = jsonObject.getInt(ConnectConstants.PLAYER_ID);
186 | } catch (JSONException e) {
187 | e.printStackTrace();
188 | }
189 | if (pid == mId) {
190 | return;
191 | }
192 | Player netPlayer = mPlayers.get(pid);
193 | netPlayer.setState(Player.STATE_DIE);
194 | netPlayer.setDirection(0);
195 | }
196 |
197 | public void noticeMyMove() {
198 | if (!SceneManager.isMultiStage()) return;
199 |
200 | Message msg = Message.obtain();
201 | msg.what = GameConstants.PLAYER_MOVE;
202 |
203 | JSONObject jsonObject = new JSONObject();
204 | try {
205 | jsonObject.put(ConnectConstants.TYPE, GameConstants.PLAYER_MOVE);
206 | jsonObject.put(ConnectConstants.PLAYER_ID, mId);
207 | jsonObject.put(ConnectConstants.DIRECTION, mMyPlayer.getDirection());
208 | jsonObject.put(ConnectConstants.POINT_X, mMyPlayer.getX());
209 | jsonObject.put(ConnectConstants.POINT_Y, mMyPlayer.getY());
210 | } catch (JSONException e) {
211 | e.printStackTrace();
212 | }
213 |
214 | msg.obj = jsonObject;
215 | mHandler.sendMessage(msg);
216 | }
217 |
218 |
219 | private void noticeMyPlayer() {
220 | if (!SceneManager.isMultiStage()) return;
221 |
222 | Message msg = Message.obtain();
223 | msg.what = GameConstants.PLAYER_ADD;
224 |
225 | JSONObject jsonObject = new JSONObject();
226 | try {
227 | jsonObject.put(ConnectConstants.TYPE, GameConstants.PLAYER_ADD);
228 | jsonObject.put(ConnectConstants.PLAYER_ID, mId);
229 | jsonObject.put(ConnectConstants.POINT_X, mMyPlayer.getX());
230 | jsonObject.put(ConnectConstants.POINT_Y, mMyPlayer.getY());
231 | } catch (JSONException e) {
232 | e.printStackTrace();
233 | }
234 |
235 | msg.obj = jsonObject;
236 | mHandler.sendMessage(msg);
237 | }
238 |
239 | public void noticeMyStop() {
240 | if (!SceneManager.isMultiStage()) return;
241 |
242 | Message msg = Message.obtain();
243 | msg.what = GameConstants.PLAYER_STOP;
244 |
245 | JSONObject jsonObject = new JSONObject();
246 | try {
247 | jsonObject.put(ConnectConstants.TYPE, GameConstants.PLAYER_STOP);
248 | jsonObject.put(ConnectConstants.PLAYER_ID, mId);
249 | } catch (JSONException e) {
250 | e.printStackTrace();
251 | }
252 | msg.obj = jsonObject;
253 | mHandler.sendMessage(msg);
254 | }
255 |
256 | public void noticeMyDie() {
257 | mMyPlayer.setState(Player.STATE_DIE);
258 |
259 | Message msg = Message.obtain();
260 | msg.what = GameConstants.PLAYER_DIE;
261 |
262 | JSONObject jsonObject = new JSONObject();
263 | try {
264 | jsonObject.put(ConnectConstants.TYPE, GameConstants.PLAYER_DIE);
265 | jsonObject.put(ConnectConstants.PLAYER_ID, mId);
266 | } catch (JSONException e) {
267 | e.printStackTrace();
268 | }
269 | msg.obj = jsonObject;
270 | mHandler.sendMessage(msg);
271 | }
272 | }
273 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/util/SPUtils.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.util;
2 |
3 | /**
4 | * Created by Liao on 2016/6/5 0005.
5 | */
6 |
7 | import java.lang.reflect.InvocationTargetException;
8 | import java.lang.reflect.Method;
9 | import java.util.Map;
10 |
11 | import android.content.Context;
12 | import android.content.SharedPreferences;
13 |
14 | public class SPUtils {
15 | /**
16 | * 保存在手机里面的文件名
17 | */
18 | public static final String FILE_NAME = "share_data";
19 |
20 | /**
21 | * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
22 | *
23 | * @param context
24 | * @param key
25 | * @param object
26 | */
27 | public static void put(Context context, String key, Object object) {
28 |
29 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
30 | SharedPreferences.Editor editor = sp.edit();
31 |
32 | if (object instanceof String) {
33 | editor.putString(key, (String) object);
34 | } else if (object instanceof Integer) {
35 | editor.putInt(key, (Integer) object);
36 | } else if (object instanceof Boolean) {
37 | editor.putBoolean(key, (Boolean) object);
38 | } else if (object instanceof Float) {
39 | editor.putFloat(key, (Float) object);
40 | } else if (object instanceof Long) {
41 | editor.putLong(key, (Long) object);
42 | } else {
43 | editor.putString(key, object.toString());
44 | }
45 |
46 | SharedPreferencesCompat.apply(editor);
47 | }
48 |
49 | /**
50 | * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
51 | *
52 | * @param context
53 | * @param key
54 | * @param defaultObject
55 | * @return
56 | */
57 | public static Object get(Context context, String key, Object defaultObject) {
58 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
59 | Context.MODE_PRIVATE);
60 |
61 | if (defaultObject instanceof String) {
62 | return sp.getString(key, (String) defaultObject);
63 | } else if (defaultObject instanceof Integer) {
64 | return sp.getInt(key, (Integer) defaultObject);
65 | } else if (defaultObject instanceof Boolean) {
66 | return sp.getBoolean(key, (Boolean) defaultObject);
67 | } else if (defaultObject instanceof Float) {
68 | return sp.getFloat(key, (Float) defaultObject);
69 | } else if (defaultObject instanceof Long) {
70 | return sp.getLong(key, (Long) defaultObject);
71 | }
72 |
73 | return null;
74 | }
75 |
76 | /**
77 | * 移除某个key值已经对应的值
78 | *
79 | * @param context
80 | * @param key
81 | */
82 | public static void remove(Context context, String key) {
83 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
84 | SharedPreferences.Editor editor = sp.edit();
85 | editor.remove(key);
86 | SharedPreferencesCompat.apply(editor);
87 | }
88 |
89 | /**
90 | * 清除所有数据
91 | *
92 | * @param context
93 | */
94 | public static void clear(Context context) {
95 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
96 | SharedPreferences.Editor editor = sp.edit();
97 | editor.clear();
98 | SharedPreferencesCompat.apply(editor);
99 | }
100 |
101 | /**
102 | * 查询某个key是否已经存在
103 | *
104 | * @param context
105 | * @param key
106 | * @return
107 | */
108 | public static boolean contains(Context context, String key) {
109 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
110 | return sp.contains(key);
111 | }
112 |
113 | /**
114 | * 返回所有的键值对
115 | *
116 | * @param context
117 | * @return
118 | */
119 | public static Map getAll(Context context) {
120 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
121 | return sp.getAll();
122 | }
123 |
124 | /**
125 | * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
126 | *
127 | * @author zhy
128 | */
129 | private static class SharedPreferencesCompat {
130 | private static final Method sApplyMethod = findApplyMethod();
131 |
132 | /**
133 | * 反射查找apply的方法
134 | *
135 | * @return
136 | */
137 | private static Method findApplyMethod() {
138 | try {
139 | Class clazz = SharedPreferences.Editor.class;
140 | return clazz.getMethod("apply");
141 | } catch (NoSuchMethodException e) {
142 | }
143 |
144 | return null;
145 | }
146 |
147 | /**
148 | * 如果找到则使用apply执行,否则使用commit
149 | *
150 | * @param editor
151 | */
152 | public static void apply(SharedPreferences.Editor editor) {
153 | try {
154 | if (sApplyMethod != null) {
155 | sApplyMethod.invoke(editor);
156 | return;
157 | }
158 | } catch (Exception e) {
159 | e.printStackTrace();
160 | }
161 | editor.commit();
162 | }
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/util/SceneManager.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.util;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Point;
6 | import android.os.Handler;
7 | import android.os.Message;
8 | import android.util.Log;
9 |
10 | import com.kuoruan.bomberman.dao.GameDataDao;
11 | import com.kuoruan.bomberman.dao.GameLevelDataDao;
12 | import com.kuoruan.bomberman.entity.Bomb;
13 | import com.kuoruan.bomberman.entity.BombFire;
14 | import com.kuoruan.bomberman.entity.Collision;
15 | import com.kuoruan.bomberman.entity.GameTile;
16 | import com.kuoruan.bomberman.entity.Player;
17 | import com.kuoruan.bomberman.entity.data.GameData;
18 | import com.kuoruan.bomberman.entity.data.GameLevelData;
19 |
20 | import org.json.JSONException;
21 | import org.json.JSONObject;
22 |
23 | import java.util.ArrayList;
24 | import java.util.HashMap;
25 | import java.util.List;
26 | import java.util.Map;
27 |
28 | /**
29 | * Created by Liao on 2016/5/8 0008.
30 | */
31 | public class SceneManager {
32 |
33 | private final String TAG = "SceneManager";
34 |
35 | public static int sceneXMax = 0;
36 | public static int sceneYMax = 0;
37 |
38 | public static int tileWidth = 0;
39 | public static int tileHeight = 0;
40 |
41 | public static int mTotalBombCount = GameConstants.DEFAULT_BOMB_COUNT;
42 | public static int gameStage = 0;
43 |
44 | private int mPlayerBombCount = 0;
45 | private int mBombType = Bomb.NORMAL;
46 | private int mFireType = BombFire.NORMAL;
47 |
48 | private Map mTileData = null;
49 | private Map mBombData = null;
50 | private Map mFireData = null;
51 |
52 | private Map> mBombTemplates = new HashMap<>();
53 | private Map>> mFireTemplates = new HashMap<>();
54 |
55 | //地图上所有的砖块
56 | private GameTile[][] mGameTiles = null;
57 | private List mBombFires = new ArrayList<>();
58 | //玩家周围的砖块
59 | private List mSurroundTiles = new ArrayList<>();
60 | private Context mContext;
61 | private Handler mHandler;
62 |
63 | private GameDataDao mGameDataDao;
64 | private GameLevelDataDao mGameLevelDataDao;
65 | private GameLevelData mGameLevelData;
66 |
67 | public SceneManager(Context context, Handler handler, int stage) {
68 | mContext = context;
69 | mHandler = handler;
70 | gameStage = stage;
71 | mGameDataDao = GameDataDao.getInstance(context);
72 | this.mTileData = mGameDataDao.getGameTileData();
73 | this.mBombData = mGameDataDao.getBombData();
74 | this.mFireData = mGameDataDao.getFireData();
75 | mGameLevelDataDao = GameLevelDataDao.getInstance(context);
76 | }
77 |
78 | /**
79 | * 处理地图数据
80 | */
81 | public GameTile[][] parseGameTileData() {
82 | mGameLevelData = mGameLevelDataDao.getGameLevelData(gameStage);
83 | String levelTileData = mGameLevelData.getLevelTiles();
84 |
85 | if (levelTileData == null) {
86 | return null;
87 | }
88 |
89 | Bitmap bitmap;
90 | Point tilePoint = new Point();
91 | int tileX = 0;
92 | int tileY = 0;
93 |
94 | String[] tileLines = levelTileData.split(GameLevelDataDao.TILE_DATA_LINE_BREAK);
95 | int rows = tileLines.length;
96 | int cols = 0;
97 |
98 | for (int i = 0; i < rows; i++) {
99 | String[] tiles = tileLines[i].split(",");
100 |
101 | //如果没有列数目
102 | if (cols == 0 && mGameTiles == null) {
103 | cols = tiles.length;
104 | mGameTiles = new GameTile[rows][cols];
105 | }
106 |
107 | for (int j = 0; j < cols; j++) {
108 | int tileNum = Integer.parseInt(tiles[j]);
109 | GameData gameTileData = mTileData.get(tileNum);
110 |
111 | if ((mGameTiles.length > 0) && (gameTileData != null)) {
112 | tilePoint.x = tileX;
113 | tilePoint.y = tileY;
114 |
115 | bitmap = BitmapManager.setAndGetBitmap(mContext, gameTileData.getDrawable());
116 | GameTile gameTile = new GameTile(bitmap, tilePoint, gameTileData.getSubType());
117 | gameTile.setVisible(gameTileData.isVisible());
118 |
119 | if (tileWidth == 0) {
120 | tileWidth = gameTile.getWidth();
121 | }
122 | if (tileHeight == 0) {
123 | tileHeight = gameTile.getHeight();
124 | }
125 |
126 | if (sceneXMax == 0 && cols > 0) {
127 | sceneXMax = cols * tileWidth;
128 | }
129 | if (sceneYMax == 0 && rows > 0) {
130 | sceneYMax = rows * tileHeight;
131 | }
132 |
133 | mGameTiles[i][j] = gameTile;
134 | }
135 |
136 | tileX += tileWidth;
137 | }
138 | tileX = 0;
139 | tileY += tileHeight;
140 | }
141 |
142 | return mGameTiles;
143 | }
144 |
145 | /**
146 | * 获取炸弹模版
147 | *
148 | * @param bombType
149 | */
150 | public List setAndGetBombTemplates(int bombType) {
151 | if (!mBombTemplates.containsKey(bombType)) {
152 | GameData data = mBombData.get(bombType);
153 |
154 | Bitmap baseBitmap = BitmapManager.setAndGetBitmap(mContext, data.getDrawable());
155 | List bitmaps = new ArrayList<>();
156 |
157 | int baseWidth = baseBitmap.getWidth();
158 | int baseHeight = baseBitmap.getHeight();
159 | int width = baseWidth / 2;
160 |
161 | for (int x = 0; x < baseWidth; x += width) {
162 | Bitmap bitmap = Bitmap.createBitmap(baseBitmap, x, 0, width, baseHeight);
163 | bitmaps.add(bitmap);
164 | }
165 |
166 | mBombTemplates.put(bombType, bitmaps);
167 | }
168 |
169 | return mBombTemplates.get(bombType);
170 | }
171 |
172 | /**
173 | * 根据火焰类型和子类型(上、下、左、右、中)或者图片列表
174 | *
175 | * @param fireType
176 | * @param fireSubType
177 | * @return
178 | */
179 | public List setAndGetFireTemplates(int fireType, int fireSubType) {
180 | if (!mFireTemplates.containsKey(fireType)) {
181 | GameData data = mFireData.get(fireType);
182 | Bitmap fireMain = BitmapManager.setAndGetBitmap(mContext, data.getDrawable());
183 |
184 | int width = fireMain.getWidth() / 4;
185 | int height = fireMain.getHeight() / 7;
186 |
187 | Map> subFires = new HashMap<>();
188 | for (int y = 0; y < 7; y++) {
189 | List list = new ArrayList<>();
190 | for (int x = 0; x < 4; x++) {
191 | Bitmap bitmap = Bitmap.createBitmap(fireMain, x * width, y * height, width, height);
192 | list.add(bitmap);
193 | }
194 |
195 | subFires.put(y + 1, list);
196 | }
197 |
198 | mFireTemplates.put(fireType, subFires);
199 | }
200 |
201 | return mFireTemplates.get(fireType).get(fireSubType);
202 | }
203 |
204 | /**
205 | * 炸弹爆炸,创建火焰
206 | *
207 | * @param bomb
208 | */
209 | public void explodBomb(Bomb bomb, int x, int y) {
210 | int fireLength = bomb.getFireLength();
211 |
212 | BombFire middleFire = new BombFire(setAndGetFireTemplates(mFireType, BombFire.TYPE_CENTER));
213 | middleFire.setMapPoint(x, y);
214 | mBombFires.add(middleFire);
215 |
216 | //火焰是否可以向四个方向延伸
217 | boolean spreadUp = true;
218 | boolean spreadDown = true;
219 | boolean spreadLeft = true;
220 | boolean spreadRight = true;
221 |
222 | int newX;
223 | int newY;
224 |
225 | for (int i = 1; i <= fireLength; i++) {
226 | //是否是最后一次循环
227 | boolean isLast = (i == fireLength);
228 | //上面
229 | newY = y - i;
230 | if (spreadUp && canSpread(mGameTiles[newY][x])) {
231 | BombFire upFire;
232 | if (!isLast) {
233 | upFire = new BombFire(setAndGetFireTemplates(mFireType, BombFire.TYPE_VERTICAL));
234 | } else {
235 | upFire = new BombFire(setAndGetFireTemplates(mFireType, BombFire.TYPE_UP));
236 | }
237 | upFire.setMapPoint(x, newY);
238 | mBombFires.add(upFire);
239 | } else {
240 | spreadUp = false;
241 | }
242 |
243 | //下面
244 | newY = y + i;
245 | if (spreadDown && canSpread(mGameTiles[newY][x])) {
246 | BombFire downFire;
247 | if (!isLast) {
248 | downFire = new BombFire(setAndGetFireTemplates(mFireType, BombFire.TYPE_VERTICAL));
249 | } else {
250 | downFire = new BombFire(setAndGetFireTemplates(mFireType, BombFire.TYPE_DOWN));
251 | }
252 | downFire.setMapPoint(x, newY);
253 | mBombFires.add(downFire);
254 | } else {
255 | spreadDown = false;
256 | }
257 |
258 | //左面
259 | newX = x - i;
260 | if (spreadLeft && canSpread(mGameTiles[y][newX])) {
261 | BombFire leftFire;
262 | if (!isLast) {
263 | leftFire = new BombFire(setAndGetFireTemplates(mFireType, BombFire.TYPE_HORIZONTAL));
264 | } else {
265 | leftFire = new BombFire(setAndGetFireTemplates(mFireType, BombFire.TYPE_LEFT));
266 | }
267 | leftFire.setMapPoint(newX, y);
268 | mBombFires.add(leftFire);
269 | } else {
270 | spreadLeft = false;
271 | }
272 |
273 | //右面
274 | newX = x + i;
275 | if (spreadRight && canSpread(mGameTiles[y][newX])) {
276 | BombFire rightFire;
277 | if (!isLast) {
278 | rightFire = new BombFire(setAndGetFireTemplates(mFireType, BombFire.TYPE_HORIZONTAL));
279 | } else {
280 | rightFire = new BombFire(setAndGetFireTemplates(mFireType, BombFire.TYPE_RIGHT));
281 | }
282 | rightFire.setMapPoint(newX, y);
283 | mBombFires.add(rightFire);
284 | } else {
285 | spreadRight = false;
286 | }
287 |
288 | }
289 | }
290 |
291 | /**
292 | * 放置炸弹
293 | *
294 | * @param mapPoint
295 | */
296 | public void setBomb(Point mapPoint) {
297 | //地图上的相对点
298 | int mapX = mapPoint.x;
299 | int mapY = mapPoint.y;
300 |
301 | GameTile gameTile = mGameTiles[mapY][mapX];
302 | if (gameTile != null && gameTile.isBlockerTile()) {
303 | Log.i(TAG, "setBomb: 炸弹已存在");
304 | return;
305 | }
306 |
307 | addBomb(PlayerManager.mId, mBombType, mapX, mapY);
308 | //网络通告
309 | noticeSetBomb(PlayerManager.mId, mapX, mapY);
310 | }
311 |
312 | private void addBomb(int pid, int bombType, int mapX, int mapY) {
313 | //计算绝对坐标点
314 | Point point = new Point();
315 | point.x = mapX * tileWidth;
316 | point.y = mapY * tileHeight;
317 |
318 | List bombTemplate = setAndGetBombTemplates(bombType);
319 | Bomb bomb = new Bomb(bombTemplate, true, point, pid);
320 | mGameTiles[mapY][mapX] = bomb;
321 | }
322 |
323 | private void noticeSetBomb(int pid, int mapX, int mapY) {
324 | if (!isMultiStage()) return;
325 |
326 | Message msg = Message.obtain();
327 | msg.what = GameConstants.SET_BOMB;
328 |
329 | JSONObject jsonObject = new JSONObject();
330 | try {
331 | jsonObject.put(ConnectConstants.TYPE, GameConstants.SET_BOMB);
332 | jsonObject.put(ConnectConstants.PLAYER_ID, pid);
333 | jsonObject.put(ConnectConstants.BOMB_TYPE, mBombType);
334 | jsonObject.put(ConnectConstants.MAP_X, mapX);
335 | jsonObject.put(ConnectConstants.MAP_Y, mapY);
336 | } catch (JSONException e) {
337 | e.printStackTrace();
338 | }
339 |
340 | msg.obj = jsonObject;
341 | mHandler.sendMessage(msg);
342 | }
343 |
344 | public void handleCollision(Collision collision, Player player) {
345 | Point mapPoint = player.getStandardMapPoint();
346 | int width = player.getWidth();
347 | int height = player.getHeight();
348 |
349 | mSurroundTiles.clear();
350 |
351 | //首先获取周围8个位置和当前位置砖块,取当前位置是为了判断是否有火焰
352 | mSurroundTiles.add(mGameTiles[mapPoint.y - 1][mapPoint.x - 1]); //左上
353 | mSurroundTiles.add(mGameTiles[mapPoint.y - 1][mapPoint.x]); //上
354 | mSurroundTiles.add(mGameTiles[mapPoint.y - 1][mapPoint.x + 1]); //右上
355 | mSurroundTiles.add(mGameTiles[mapPoint.y][mapPoint.x - 1]); //左
356 | mSurroundTiles.add(mGameTiles[mapPoint.y][mapPoint.x]); //当前
357 | mSurroundTiles.add(mGameTiles[mapPoint.y][mapPoint.x + 1]); //右
358 | mSurroundTiles.add(mGameTiles[mapPoint.y + 1][mapPoint.x - 1]); //左下
359 | mSurroundTiles.add(mGameTiles[mapPoint.y + 1][mapPoint.x]); //下
360 | mSurroundTiles.add(mGameTiles[mapPoint.y + 1][mapPoint.x + 1]); //右下
361 |
362 | GameTile collisionTile = null;
363 | int newX = collision.getNewX();
364 | int newY = collision.getNewY();
365 |
366 | for (GameTile gameTile : mSurroundTiles) {
367 | if (gameTile != null && gameTile.isCollision(newX, newY, width, height)) {
368 | //如果存在冲突
369 | collisionTile = gameTile;
370 | break;
371 | }
372 | }
373 | if (collisionTile == null) {
374 | return;
375 | }
376 |
377 | if (collisionTile.getType() == GameTile.TYPE_BOMB) {
378 | Point nowPoint = player.getPoint();
379 | if (collisionTile.isCollision(nowPoint.x, nowPoint.y, width, height)) { //如果炸弹和当前角色有交叉
380 | return; //允许通过
381 | } else {
382 | collision.setSolvable(false); //不许通过
383 | return;
384 | }
385 | }
386 |
387 | collision.setCollisionTile(collisionTile);
388 | collision.solveCollision();
389 | }
390 |
391 | public List getBombFires() {
392 | return mBombFires;
393 | }
394 |
395 | /**
396 | * 判断砖块是否是空或者可以破环
397 | *
398 | * @param gameTile
399 | * @return
400 | */
401 | private boolean canSpread(GameTile gameTile) {
402 | return gameTile == null || !gameTile.isBlockerTile();
403 | }
404 |
405 | /**
406 | * 判断游戏是否为多人游戏
407 | *
408 | * @return
409 | */
410 | public static boolean isMultiStage() {
411 | return gameStage == GameConstants.MULTI_PLAYER_STAGE;
412 | }
413 |
414 | /**
415 | * 处理网络炸弹放置
416 | */
417 | public void handleSetBomb(JSONObject jsonObject) {
418 | int pid = 0;
419 | int bombType = 0;
420 | int mapX = 0;
421 | int mapY = 0;
422 |
423 | try {
424 | pid = jsonObject.getInt(ConnectConstants.PLAYER_ID);
425 | bombType = jsonObject.getInt(ConnectConstants.BOMB_TYPE);
426 | mapX = jsonObject.getInt(ConnectConstants.MAP_X);
427 | mapY = jsonObject.getInt(ConnectConstants.MAP_Y);
428 | } catch (JSONException e) {
429 | e.printStackTrace();
430 | }
431 |
432 | addBomb(pid, bombType, mapX, mapY);
433 | }
434 | }
435 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kuoruan/bomberman/view/GameView.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapFactory;
6 | import android.graphics.Canvas;
7 | import android.graphics.Paint;
8 | import android.graphics.Point;
9 | import android.util.DisplayMetrics;
10 | import android.util.Log;
11 | import android.view.Display;
12 | import android.view.MotionEvent;
13 | import android.view.SurfaceHolder;
14 | import android.view.SurfaceView;
15 |
16 | import com.kuoruan.bomberman.R;
17 | import com.kuoruan.bomberman.entity.Bomb;
18 | import com.kuoruan.bomberman.entity.BombFire;
19 | import com.kuoruan.bomberman.entity.Collision;
20 | import com.kuoruan.bomberman.entity.GameTile;
21 | import com.kuoruan.bomberman.entity.GameUi;
22 | import com.kuoruan.bomberman.entity.Player;
23 | import com.kuoruan.bomberman.util.BitmapManager;
24 | import com.kuoruan.bomberman.util.SceneManager;
25 | import com.kuoruan.bomberman.util.PlayerManager;
26 |
27 | import java.util.ArrayList;
28 | import java.util.Collection;
29 | import java.util.List;
30 | import java.util.Map;
31 |
32 | /**
33 | * 游戏地图view
34 | */
35 | public class GameView extends SurfaceView implements SurfaceHolder.Callback {
36 |
37 | private static final String TAG = "GameView";
38 | //每30毫秒刷新一次屏幕
39 | public static final int TIME_IN_FRAME = 30;
40 | //控制按钮边距
41 | private static final int CONTROLS_PADDING = 10;
42 | //游戏状态
43 | public static final int STATE_RUNNING = 1;
44 | public static final int STATE_PAUSED = 2;
45 |
46 | //屏幕大小
47 | private int mScreenXMax = 0;
48 | private int mScreenYMax = 0;
49 | private int mScreenXCenter = 0;
50 | private int mScreenYCenter = 0;
51 |
52 | /**
53 | * 屏幕偏移
54 | */
55 | private int mScreenXOffset = 0;
56 | private int mScreenYOffset = 0;
57 |
58 | //主线程运行
59 | private boolean mGameRun = true;
60 | //游戏状态
61 | private int mGameState;
62 |
63 | private Display mDisplay;
64 |
65 | //屏幕像素密度
66 | private float mScreenDensity = 0.0f;
67 | private SurfaceHolder mGameSurfaceHolder;
68 | //正在处理地图
69 | private boolean updatingGameTiles = false;
70 |
71 | //当前玩家
72 | private Player mPlayer;
73 |
74 | //文字画笔
75 | private Paint mUiTextPaint;
76 | private Context mGameContext;
77 |
78 | //控制按钮
79 | private GameUi mCtrlUpArrow;
80 | private GameUi mCtrlDownArrow;
81 | private GameUi mCtrlLeftArrow;
82 | private GameUi mCtrlRightArrow;
83 | private GameUi mSetBombButton;
84 | //背景图片
85 | private Bitmap mBackgroundImage;
86 |
87 | //地图对象数组
88 | private GameTile[][] mGameTiles;
89 | private List mBombFires;
90 | private List mEndFires = new ArrayList<>();
91 |
92 | private PlayerManager mPlayerManager;
93 | private SceneManager mSceneManager;
94 | private Map mPlayers;
95 | //冲突对象
96 | private Collision mCollision = new Collision();
97 |
98 | //游戏主线程
99 | private GameThread mThread;
100 |
101 | public GameView(Context context) {
102 | super(context);
103 | }
104 |
105 | public GameView(Context context, PlayerManager playerManager, SceneManager sceneManager, Display display) {
106 | super(context);
107 | mGameContext = context;
108 | mDisplay = display;
109 |
110 | mPlayerManager = playerManager;
111 | mPlayer = mPlayerManager.getMyPlayer();
112 | mPlayers = mPlayerManager.getPlayers();
113 |
114 | mSceneManager = sceneManager;
115 | mBombFires = mSceneManager.getBombFires();
116 |
117 | SurfaceHolder holder = getHolder();
118 | holder.addCallback(this);
119 | //游戏主线程
120 | mThread = new GameThread(holder, context);
121 |
122 | setFocusable(true);
123 |
124 | //初始化关卡数据
125 | startLevel();
126 | mThread.doStart();
127 | }
128 |
129 | @Override
130 | public void surfaceCreated(SurfaceHolder holder) {
131 | if (mThread.getState() == Thread.State.TERMINATED) {
132 | mThread = new GameThread(holder, getContext());
133 | mThread.setRunning(true);
134 | mThread.start();
135 | mThread.doStart();
136 | startLevel();
137 | } else {
138 | mThread.setRunning(true);
139 | mThread.start();
140 | }
141 | }
142 |
143 | @Override
144 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
145 | mThread.setSurfaceSize(width, height);
146 | }
147 |
148 | @Override
149 | public void surfaceDestroyed(SurfaceHolder holder) {
150 | boolean retry = true;
151 | mThread.setRunning(false);
152 | while (retry) {
153 | try {
154 | mThread.join();
155 | retry = false;
156 | } catch (InterruptedException e) {
157 | Log.e(TAG, e.getMessage());
158 | }
159 | }
160 | }
161 |
162 | public class GameThread extends Thread {
163 |
164 | //画布
165 | private Canvas canvas = null;
166 |
167 | public GameThread(SurfaceHolder surfaceHolder, Context context) {
168 | mGameSurfaceHolder = surfaceHolder;
169 | mGameContext = context;
170 | mBackgroundImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.game_bg);
171 |
172 | //获取屏幕相关数据
173 | Point point = new Point();
174 | mDisplay.getSize(point);
175 | mScreenXMax = point.x;
176 | mScreenYMax = point.y;
177 |
178 | mScreenXCenter = (mScreenXMax / 2);
179 | mScreenYCenter = (mScreenYMax / 2);
180 | //获取屏幕像素密度
181 | DisplayMetrics outMetrics = new DisplayMetrics();
182 | mDisplay.getMetrics(outMetrics);
183 | mScreenDensity = outMetrics.density;
184 |
185 | setGameStartState();
186 | }
187 |
188 | @Override
189 | public void run() {
190 | while (mGameRun) {
191 | //取得更新游戏之前的时间
192 | long startTime = System.currentTimeMillis();
193 | try {
194 | synchronized (mGameSurfaceHolder) {
195 | canvas = mGameSurfaceHolder.lockCanvas();
196 | if (mGameState == STATE_RUNNING) {
197 | updatePlayer();
198 | }
199 | doDraw();
200 | }
201 | } finally {
202 | if (canvas != null) {
203 | mGameSurfaceHolder.unlockCanvasAndPost(canvas);
204 | }
205 | }
206 |
207 | long endTime = System.currentTimeMillis();
208 | //计算出游戏一次更新的毫秒数
209 | int diffTime = (int) (endTime - startTime);
210 |
211 | //确保每次更新时间为30毫秒
212 | while (diffTime <= TIME_IN_FRAME) {
213 | diffTime = (int) (System.currentTimeMillis() - startTime);
214 | //线程等待
215 | Thread.yield();
216 | }
217 |
218 | }
219 | }
220 |
221 | public void setSurfaceSize(int width, int height) {
222 | synchronized (mGameSurfaceHolder) {
223 | mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, width, height, true);
224 | }
225 | }
226 |
227 |
228 | public void setRunning(boolean run) {
229 | mGameRun = run;
230 | }
231 |
232 | //更新自身游戏角色位置
233 | private void updatePlayer() {
234 | if (mPlayer != null && mPlayer.isMoving()) {
235 | int newX = mPlayer.getX();
236 | int newY = mPlayer.getY();
237 | int direction = mPlayer.getDirection();
238 | int pixelValue = getPixelValueForDensity(mPlayer.getSpeed());
239 |
240 | switch (direction) {
241 | case Player.DIRECTION_UP:
242 | newY -= pixelValue;
243 | break;
244 | case Player.DIRECTION_DOWN:
245 | newY += pixelValue;
246 | break;
247 | case Player.DIRECTION_LEFT:
248 | newX -= pixelValue;
249 | break;
250 | case Player.DIRECTION_RIGHT:
251 | newX += pixelValue;
252 | break;
253 | }
254 |
255 | mCollision.setDirection(direction);
256 | mCollision.setSolvable(true);
257 | mCollision.setNewX(newX);
258 | mCollision.setNewY(newY);
259 |
260 | mSceneManager.handleCollision(mCollision, mPlayer);
261 |
262 | if (mCollision.isSolvable()) {
263 | mPlayer.setX(mCollision.getNewX());
264 | mPlayer.setY(mCollision.getNewY());
265 | mPlayerManager.noticeMyMove();
266 | setViewOffset();
267 | } else {
268 | handleTileCollision(mCollision.getCollisionTile());
269 | }
270 |
271 | }
272 | }
273 |
274 | //绘制游戏元素
275 | private void doDraw() {
276 | if (canvas != null) {
277 | canvas.drawBitmap(mBackgroundImage, 0, 0, null);
278 |
279 | if (!updatingGameTiles) {
280 | drawGameTiles();
281 | }
282 | drawBombFires();
283 | drawPlayers();
284 | drawControls();
285 |
286 | //canvas.drawText(mLastStatusMessage, 30, 50, mUiTextPaint);
287 | }
288 | }
289 |
290 | //绘制玩家
291 | private void drawPlayers() {
292 | int offsetX;
293 | int offsetY;
294 |
295 | Collection players = mPlayers.values();
296 | for (Player player : players) {
297 | offsetX = player.getX() - mScreenXOffset;
298 | offsetY = player.getY() - mScreenYOffset;
299 | //Log.i(TAG, "drawPlayers: player" + player.getId() + " is moving " + player.isMoving());
300 | if (player.isMoving() || (!player.isAlive() && !player.isEnd())) {
301 | player.doAnimation();
302 | }
303 | canvas.drawBitmap(player.getBitmap(), offsetX, offsetY, null);
304 | }
305 | }
306 |
307 | //绘制游戏地图
308 | private void drawGameTiles() {
309 | int offsetX;
310 | int offsetY;
311 | int type;
312 | GameTile gameTile;
313 |
314 | for (int i = 0; i < mGameTiles.length; i++) {
315 | for (int j = 0; j < mGameTiles[i].length; j++) {
316 | gameTile = mGameTiles[i][j];
317 | if (gameTile == null) {
318 | continue;
319 | }
320 | offsetX = gameTile.getX() - mScreenXOffset;
321 | offsetY = gameTile.getY() - mScreenYOffset;
322 |
323 | if (gameTile.isVisible()) {
324 | type = gameTile.getType(); //获取砖块类型
325 |
326 | switch (type) {
327 | case GameTile.TYPE_BOMB:
328 | Bomb bomb = (Bomb) gameTile;
329 | if (bomb.isExplosion()) { //如果炸弹已爆炸
330 | mSceneManager.explodBomb(bomb, j, i); //引爆炸弹
331 | mGameTiles[i][j] = null;
332 | } else {
333 | bomb.doAnimation();
334 | }
335 | break;
336 |
337 | default:
338 | break;
339 | }
340 |
341 | canvas.drawBitmap(gameTile.getBitmap(), offsetX, offsetY, null);
342 | }
343 | }
344 | }
345 | }
346 |
347 | private void drawBombFires() {
348 | if (mBombFires.size() == 0) {
349 | return;
350 | }
351 |
352 | int offsetX;
353 | int offsetY;
354 | for (GameTile fire : mBombFires) {
355 | if (fire.isCollision(mPlayer.getX(), mPlayer.getY(), mPlayer.getWidth(), mPlayer.getHeight())) {
356 | mPlayerManager.noticeMyDie();
357 | }
358 | if (fire.isEnd()) {
359 | mEndFires.add(fire);
360 | } else {
361 | offsetX = fire.getX() - mScreenXOffset;
362 | offsetY = fire.getY() - mScreenYOffset;
363 | fire.doAnimation();
364 | canvas.drawBitmap(fire.getBitmap(), offsetX, offsetY, null);
365 | }
366 | }
367 |
368 | mBombFires.removeAll(mEndFires);
369 | mEndFires.clear();
370 | }
371 |
372 | //绘制控制按钮
373 | private void drawControls() {
374 | canvas.drawBitmap(mCtrlUpArrow.getBitmap(), mCtrlUpArrow.getX(), mCtrlUpArrow.getY(), null);
375 | canvas.drawBitmap(mCtrlDownArrow.getBitmap(), mCtrlDownArrow.getX(), mCtrlDownArrow.getY(), null);
376 | canvas.drawBitmap(mCtrlLeftArrow.getBitmap(), mCtrlLeftArrow.getX(), mCtrlLeftArrow.getY(), null);
377 | canvas.drawBitmap(mCtrlRightArrow.getBitmap(), mCtrlRightArrow.getX(), mCtrlRightArrow.getY(), null);
378 | canvas.drawBitmap(mSetBombButton.getBitmap(), mSetBombButton.getX(), mSetBombButton.getY(), null);
379 | }
380 |
381 | //设置游戏状态
382 | public void setState(int state) {
383 | mGameState = state;
384 | }
385 |
386 | //游戏暂停
387 | public void pause() {
388 | synchronized (mGameSurfaceHolder) {
389 | if (mGameState == STATE_RUNNING) {
390 | setState(STATE_PAUSED);
391 | }
392 | }
393 | }
394 |
395 | //开始游戏
396 | public void doStart() {
397 | setState(STATE_RUNNING);
398 | }
399 |
400 | //游戏继续
401 | public void unPause() {
402 | synchronized (mGameSurfaceHolder) {
403 | if (mGameState != STATE_RUNNING) {
404 | setState(STATE_RUNNING);
405 | }
406 | }
407 | }
408 |
409 | private void setGameStartState() {
410 | setControlsStart();
411 | setViewOffset();
412 | }
413 |
414 | //处理控制按钮
415 | private void setControlsStart() {
416 | if (mCtrlDownArrow == null) {
417 |
418 | mCtrlDownArrow = new GameUi(BitmapManager.setAndGetBitmap(mGameContext, R.drawable.ctrl_down_arrow));
419 |
420 | mCtrlDownArrow.setX((mCtrlDownArrow.getWidth() + getPixelValueForDensity(CONTROLS_PADDING)));
421 | mCtrlDownArrow.setY(mScreenYMax - (mCtrlDownArrow.getHeight() + getPixelValueForDensity
422 | (CONTROLS_PADDING)));
423 | }
424 |
425 | if (mCtrlUpArrow == null) {
426 | mCtrlUpArrow = new GameUi(BitmapManager.setAndGetBitmap(mGameContext, R.drawable.ctrl_up_arrow));
427 |
428 | mCtrlUpArrow.setX(mCtrlDownArrow.getX());
429 | mCtrlUpArrow.setY(mCtrlDownArrow.getY() - (mCtrlUpArrow.getHeight() * 2));
430 | }
431 |
432 | if (mCtrlLeftArrow == null) {
433 | mCtrlLeftArrow = new GameUi(BitmapManager.setAndGetBitmap(mGameContext, R.drawable.ctrl_left_arrow));
434 | mCtrlLeftArrow.setX(mCtrlDownArrow.getX() - mCtrlLeftArrow.getWidth());
435 | mCtrlLeftArrow.setY(mCtrlDownArrow.getY() - mCtrlLeftArrow.getHeight());
436 | }
437 |
438 | if (mCtrlRightArrow == null) {
439 | mCtrlRightArrow = new GameUi(BitmapManager.setAndGetBitmap(mGameContext, R.drawable.ctrl_right_arrow));
440 |
441 | mCtrlRightArrow.setX(mCtrlLeftArrow.getX() + (mCtrlRightArrow.getWidth() * 2));
442 | mCtrlRightArrow.setY(mCtrlLeftArrow.getY());
443 | }
444 |
445 | if (mSetBombButton == null) {
446 | mSetBombButton = new GameUi(BitmapManager.setAndGetBitmap(mGameContext, R.drawable.set_bomb));
447 |
448 | mSetBombButton.setX(mScreenXMax - (mSetBombButton.getWidth() + getPixelValueForDensity
449 | (CONTROLS_PADDING)));
450 | mSetBombButton.setY(mScreenYMax - (mSetBombButton.getHeight() * 2 + getPixelValueForDensity
451 | (CONTROLS_PADDING)));
452 | }
453 | }
454 |
455 | }
456 |
457 | public GameThread getGameThread() {
458 | return mThread;
459 | }
460 |
461 | private void startLevel() {
462 | parseGameLevelData();
463 | setViewOffset();
464 |
465 | mThread.unPause();
466 | }
467 |
468 | //处理游戏数据
469 | private void parseGameLevelData() {
470 | updatingGameTiles = true;
471 |
472 | mGameTiles = mSceneManager.parseGameTileData();
473 |
474 | if (mGameTiles == null) {
475 | return;
476 | }
477 |
478 | //处理地图数据
479 | updatingGameTiles = false;
480 | }
481 |
482 | /**
483 | * 计算屏幕偏移
484 | */
485 | private void setViewOffset() {
486 | if (SceneManager.sceneXMax == 0 || SceneManager.sceneYMax == 0) {
487 | return;
488 | }
489 |
490 | int playerX = mPlayer.getX();
491 | int playerY = mPlayer.getY();
492 |
493 | if (playerX >= mScreenXCenter) {
494 | mScreenXOffset = playerX - mScreenXCenter;
495 |
496 | if (mScreenXOffset > (SceneManager.sceneXMax - mScreenXMax)) {
497 | mScreenXOffset = SceneManager.sceneXMax - mScreenXMax;
498 | }
499 | }
500 |
501 | if (playerY >= mScreenYCenter) {
502 | mScreenYOffset = playerY - mScreenYCenter;
503 |
504 | if (mScreenYOffset > (SceneManager.sceneYMax - mScreenYMax)) {
505 | mScreenYOffset = SceneManager.sceneYMax - mScreenYMax;
506 | }
507 | }
508 |
509 | }
510 |
511 | //处理点击触摸事件
512 | @Override
513 | public boolean onTouchEvent(MotionEvent event) {
514 |
515 | if (!mPlayer.isAlive()) {
516 | Log.i(TAG, "onTouchEvent: 角色已死亡");
517 | return false;
518 | }
519 |
520 | int x = (int) event.getX(0);
521 | int y = (int) event.getY(0);
522 | switch (event.getAction() & MotionEvent.ACTION_MASK) {
523 | case MotionEvent.ACTION_POINTER_DOWN:
524 | //获取第二个按下点的坐标
525 | x = (int) event.getX(1);
526 | y = (int) event.getY(1);
527 | case MotionEvent.ACTION_DOWN:
528 |
529 | if (mGameState == STATE_RUNNING) {
530 | if (mSetBombButton.getImpact(x, y)) {
531 | mSceneManager.setBomb(mPlayer.getStandardMapPoint());
532 | } else if (mCtrlUpArrow.getImpact(x, y)) {
533 | mPlayer.setDirection(Player.DIRECTION_UP);
534 | mPlayer.setState(Player.STATE_MOVING);
535 | } else if (mCtrlDownArrow.getImpact(x, y)) {
536 | mPlayer.setDirection(Player.DIRECTION_DOWN);
537 | mPlayer.setState(Player.STATE_MOVING);
538 | } else if (mCtrlLeftArrow.getImpact(x, y)) {
539 | mPlayer.setDirection(Player.DIRECTION_LEFT);
540 | mPlayer.setState(Player.STATE_MOVING);
541 | } else if (mCtrlRightArrow.getImpact(x, y)) {
542 | mPlayer.setDirection(Player.DIRECTION_RIGHT);
543 | mPlayer.setState(Player.STATE_MOVING);
544 | }
545 | }
546 | break;
547 | case MotionEvent.ACTION_UP:
548 | case MotionEvent.ACTION_CANCEL:
549 | mPlayer.setState(Player.STATE_STOP);
550 | mPlayer.setDirection(0);
551 | mPlayerManager.noticeMyStop();
552 | break;
553 | }
554 |
555 | return true;
556 | }
557 |
558 | //处理冲突
559 | private void handleTileCollision(GameTile gameTile) {
560 | if (gameTile != null) {
561 | switch (gameTile.getType()) {
562 | case GameTile.TYPE_OBSTACLE:
563 | Log.i(TAG, "handleTileCollision: 外岩");
564 | break;
565 | case GameTile.TYPE_ROCK:
566 | Log.i(TAG, "handleTileCollision: 普通岩石");
567 | break;
568 | case GameTile.TYPE_CRATES:
569 | Log.i(TAG, "handleTileCollision: 木箱子");
570 | break;
571 | case GameTile.TYPE_BOMB:
572 | Log.i(TAG, "handleTileCollision: 炸弹");
573 | break;
574 | case GameTile.TYPE_BOMB_FIRE:
575 | Log.i(TAG, "handleTileCollision: 火焰");
576 | mPlayerManager.noticeMyDie(); //处理角色死亡
577 | break;
578 | default:
579 | Log.i(TAG, "handleTileCollision: 其他冲突");
580 | }
581 | }
582 | }
583 |
584 | private int getPixelValueForDensity(int pixels) {
585 | return (int) (pixels * mScreenDensity);
586 | }
587 | }
588 |
589 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/background.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/bomb_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/bomb_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/bomb_1_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/bomb_1_0.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/bomb_1_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/bomb_1_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/btn_circle_style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
-
7 |
8 |
9 |
10 |
-
11 |
12 |
13 |
14 |
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 |
24 | -
25 |
26 |
27 |
28 |
29 |
30 |
31 | -
32 |
33 |
-
34 |
35 |
36 |
37 |
-
38 |
39 |
40 |
41 |
42 |
43 |
44 | -
45 |
46 |
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 |
57 |
58 | -
59 |
60 |
-
61 |
62 |
63 |
64 |
-
65 |
66 |
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 |
75 |
76 |
77 |
78 | -
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/btn_white_style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | -
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | -
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ctrl_down_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/ctrl_down_arrow.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ctrl_left_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/ctrl_left_arrow.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ctrl_right_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/ctrl_right_arrow.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ctrl_up_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/ctrl_up_arrow.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/fire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/fire.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/game_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/game_bg.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/player_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/player_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/player_unit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/player_unit.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/set_bomb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/set_bomb.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/tile_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/tile_01.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/tile_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/tile_02.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/tile_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-hdpi/tile_03.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/bomb_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/bomb_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/bomb_1_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/bomb_1_0.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/bomb_1_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/bomb_1_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ctrl_down_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/ctrl_down_arrow.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ctrl_left_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/ctrl_left_arrow.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ctrl_right_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/ctrl_right_arrow.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ctrl_up_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/ctrl_up_arrow.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/fire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/fire.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/game_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/game_bg.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/player_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/player_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/player_unit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/player_unit.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/set_bomb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/set_bomb.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/tile_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/tile_01.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/tile_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/tile_02.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/tile_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/drawable-mdpi/tile_03.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_connection.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
24 |
25 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
29 |
30 |
40 |
41 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/chat_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/chat_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
18 |
19 |
26 |
27 |
28 |
29 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/connection_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 炸弹人
4 | 单人游戏
5 | 联机游戏
6 | 退出游戏
7 | 关于游戏
8 | 搜索玩家
9 | 网络扫描
10 | 网络联机
11 | 玩家
12 | 正在扫描… 请稍候
13 | 希望和你对战
14 | 同意
15 | 拒绝
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #90ff0000
4 | #ff353535
5 | #ff000000
6 | #ff000000
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | BomberMan
3 | Single Play
4 | Multi Game
5 | Exit Game
6 | About Game
7 | Search Players
8 | LAN Scan
9 | Connection
10 | Game Player
11 | Scanning… Please wait.
12 | Ask for fight with you.
13 | Agree
14 | Reject
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/test/java/com/kuoruan/bomberman/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.kuoruan.bomberman;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.0-alpha4'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Sun Jun 12 13:31:18 CST 2016
16 | org.gradle.jvmargs=-Xmx1536m
17 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuoruan/Android-BomberMan/c98d5f6eef3c9393fa8adc119947f1930986aba9/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------