GameSurface.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. package com.darkdimension.ritle_run;
  2. import com.darkdimension.ritle_run.Menu.Action;
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.content.SharedPreferences;
  6. import android.graphics.Canvas;
  7. import android.graphics.Color;
  8. import android.graphics.Paint;
  9. import android.media.AudioManager;
  10. import android.media.SoundPool;
  11. import android.net.Uri;
  12. import android.view.MotionEvent;
  13. import android.view.SurfaceHolder;
  14. import android.view.SurfaceView;
  15. public class GameSurface extends SurfaceView
  16. implements SurfaceHolder.Callback, Runnable
  17. {
  18. //Thread
  19. private Thread gThread;
  20. private boolean running = false;
  21. //Surface
  22. public static int width, height;
  23. public static float density;
  24. public static boolean isPhone;
  25. //Menus
  26. private Menu menu = null;
  27. //Font
  28. public static Paint font = new Paint();
  29. //Sounds
  30. private static SoundPool soundPool;
  31. private static int sound[];
  32. public static boolean bSound;
  33. //Save-load
  34. SharedPreferences sharedPref;
  35. public GameSurface(Context context)
  36. {
  37. super(context);
  38. //Callback to Surface calls
  39. getHolder().addCallback(this);
  40. //Focus
  41. setFocusable(true);
  42. }
  43. public boolean onTouchEvent(MotionEvent event)
  44. {
  45. //Touch Current Menu
  46. if (menu != null)
  47. if (event.getAction() == MotionEvent.ACTION_DOWN
  48. && !menu.isAnimating())
  49. return menu.touch((int)event.getX(), (int)event.getY());
  50. //Return super touch
  51. return super.onTouchEvent(event);
  52. }
  53. public void update()
  54. {
  55. //Update Current Menu and act accordingly
  56. switch (menu.update())
  57. {
  58. //Menus
  59. case TO_MAIN_MENU:
  60. if (menu instanceof MenuGame)
  61. menu = new MenuMain(getResources(), ((MenuGame)menu).hardReset);
  62. else
  63. menu = new MenuMain(getResources(), false);
  64. break;
  65. case TO_GAME:
  66. if (menu instanceof MenuGame)
  67. menu = new MenuGame(getResources(), getHighScore(), ((MenuGame)menu).hardReset);
  68. else
  69. menu = new MenuGame(getResources(), getHighScore(), false);
  70. break;
  71. case TO_EXTRA:
  72. menu = new MenuExtra(getResources());
  73. break;
  74. //Exit Game
  75. case EXIT_GAME:
  76. ExitGame();
  77. break;
  78. //Social Sites
  79. case TO_PLAY_STORE:
  80. Intent playIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://market.android.com/search?q=pub:Dark Dimension"));
  81. getContext().startActivity(playIntent);
  82. break;
  83. case TO_FACEBOOK:
  84. Intent facebookIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.facebook.com/DarkDimensionGames"));
  85. getContext().startActivity(facebookIntent);
  86. break;
  87. case TO_TUMBLR:
  88. Intent tumblrIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://t0mkun.tumblr.com"));
  89. getContext().startActivity(tumblrIntent);
  90. break;
  91. case TO_TWITTER:
  92. Intent twitterIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/DDimensionGames"));
  93. getContext().startActivity(twitterIntent);
  94. break;
  95. //Ads
  96. case SHOW_AD:
  97. //Set new high score if needed
  98. if (menu instanceof MenuGame)
  99. if ( ((MenuGame)menu).hasNewHighScore() )
  100. setHighScore( ((MenuGame)menu).getHighScore() );
  101. break;
  102. case CHANGE_CHAR:
  103. DiPoint.changeCharacter(getResources());
  104. break;
  105. default:
  106. break;
  107. }
  108. }
  109. public void draw(Canvas canvas)
  110. {
  111. //Draw Current Menu
  112. menu.draw(canvas);
  113. }
  114. //Actions
  115. public void onBackPressed()
  116. {
  117. //DiPoint.changeCharacter(getResources(), 1);
  118. if (!menu.isAnimating())
  119. if (menu instanceof MenuExtra)
  120. menu.destroy(Action.TO_MAIN_MENU);
  121. else
  122. if (menu instanceof MenuGame)
  123. ((MenuGame)menu).pause();
  124. else
  125. ExitGame();
  126. }
  127. public void ExitGame()
  128. {
  129. //Stop thread's execution
  130. running = false;
  131. //Close Activity
  132. ((GameActivity)getContext()).finish();
  133. }
  134. public void DestroyThread()
  135. {
  136. //Stop thread from executing
  137. running = false;
  138. //Keep trying to join thread until it stops executing
  139. boolean retry = true;
  140. while (retry)
  141. try
  142. {
  143. gThread.join();
  144. retry = false;
  145. } catch (InterruptedException e){}
  146. //Empty Thread
  147. gThread = null;
  148. }
  149. public int getHighScore()
  150. {
  151. return sharedPref.getInt("HIGH_SCORE", 0);
  152. }
  153. public void setHighScore(int gHighScore)
  154. {
  155. SharedPreferences.Editor editor = sharedPref.edit();
  156. editor.putInt("HIGH_SCORE", gHighScore);
  157. editor.apply();
  158. }
  159. public boolean hasSound()
  160. {
  161. return sharedPref.getBoolean("HAS_SOUND", true);
  162. }
  163. //Load Sounds
  164. public void loadSounds(int...soundId)
  165. {
  166. soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
  167. sound = new int[soundId.length];
  168. for (int iii = 0; iii < sound.length; iii++)
  169. sound[iii] = soundPool.load(getContext(), soundId[iii], 0);
  170. }
  171. public static void playSound(int soundNumber)
  172. {
  173. if (bSound)
  174. soundPool.play(sound[soundNumber], 1.0f, 1.0f, 0, 0, 1.0f);
  175. }
  176. //Surface
  177. @Override
  178. public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}
  179. @Override
  180. public void surfaceCreated(SurfaceHolder holder)
  181. {
  182. if (menu == null)
  183. {
  184. //Surface
  185. width = getWidth();
  186. height = getHeight();
  187. density = getResources().getDisplayMetrics().density;
  188. isPhone = width /density < 640;
  189. sharedPref = ((GameActivity) getContext()).getPreferences(Context.MODE_PRIVATE);
  190. bSound = hasSound();
  191. //Font
  192. font.setColor(Color.WHITE);
  193. font.setTextSize( (20 +(isPhone? 0 : 12)) *GameSurface.density);
  194. font.setTextAlign(Paint.Align.CENTER);
  195. font.setAntiAlias(true);
  196. font.setShadowLayer(2, 1, 1, Color.BLACK);
  197. }
  198. else
  199. //Re-draw Menu State
  200. menu.forceDraw();
  201. //Create Thread
  202. gThread = new Thread(this);
  203. running = true;
  204. gThread.start();
  205. }
  206. @Override
  207. public void surfaceDestroyed(SurfaceHolder holder)
  208. {
  209. DestroyThread();
  210. }
  211. //Thread
  212. public void run()
  213. {
  214. //Actual Screen
  215. Canvas screen;
  216. //Load Graphics
  217. if (!DiPoint.isLoaded())
  218. {
  219. //Loading Screen
  220. screen = null;
  221. //Try locking the canvas for pixel editing on surface
  222. try
  223. {
  224. screen = getHolder().lockCanvas();
  225. if (screen != null)
  226. synchronized (getHolder())
  227. {
  228. screen.drawARGB(255, 254 ,158, 112);
  229. screen.drawText("Loading", GameSurface.width/2, GameSurface.height/2, font);
  230. }
  231. } finally{
  232. //Draw Loading screen
  233. if (screen != null)
  234. getHolder().unlockCanvasAndPost(screen);}
  235. //Load graphics
  236. DiPoint.loadGraphics(getResources(),
  237. R.drawable.background_bottom_0, //0
  238. R.drawable.background_bottom_1,
  239. R.drawable.background_top,
  240. R.drawable.cloud_back, //3
  241. R.drawable.cloud_front,
  242. R.drawable.tree_0, //5
  243. R.drawable.tree_1,
  244. R.drawable.title, //7
  245. R.drawable.button,
  246. R.drawable.tutorial,
  247. R.drawable.dark_dimension_logo, //10
  248. R.drawable.facebook,
  249. R.drawable.twitter,
  250. R.drawable.tumblr,
  251. R.drawable.google_play_store,
  252. R.drawable.ground_0_0, //15
  253. R.drawable.ground_1_0,
  254. R.drawable.ground_2_0,
  255. R.drawable.ground_damaged_0,
  256. R.drawable.ground_damaged_1,
  257. R.drawable.ground_damaged_2,
  258. R.drawable.crystal, //21
  259. R.drawable.magic_mana,
  260. R.drawable.shield,
  261. R.drawable.double_score,
  262. R.drawable.spikes,
  263. R.drawable.sound_yes, //26
  264. R.drawable.sound_no,
  265. R.drawable.darek_run_0, //28
  266. R.drawable.darek_run_1,
  267. R.drawable.darek_run_2,
  268. R.drawable.darek_run_3,
  269. R.drawable.darek_run_4,
  270. R.drawable.darek_run_5,
  271. R.drawable.darek_run_6,
  272. R.drawable.darek_run_7,
  273. R.drawable.darek_fall, //36
  274. R.drawable.darek_jump,
  275. R.drawable.shield_active_0, //38
  276. R.drawable.shield_active_1,
  277. R.drawable.air_jump_darek //40
  278. );
  279. //Load Sounds
  280. loadSounds(
  281. R.raw.foot_step,
  282. R.raw.jump,
  283. R.raw.crystal_pick_up, //2
  284. R.raw.mana_collect,
  285. R.raw.mana_lose,
  286. R.raw.double_score,
  287. R.raw.shield,
  288. //7
  289. R.raw.spikes);
  290. }//Done loading graphics/sounds
  291. //If game is starting, go to MainMenu
  292. //(if menu != null then game is resuming so there is no need for change)
  293. if (menu == null)
  294. {
  295. menu = new MenuMain(getResources(), false);
  296. Background.Initialize();
  297. }
  298. Background.aCloud.startFromBeginning();
  299. //Game Cycle
  300. while (running)
  301. {
  302. //Start Frame
  303. long startTime = System.currentTimeMillis();
  304. //Update
  305. update();
  306. //Empty screen so it can obtain new instance
  307. screen = null;
  308. if (menu.needsToBeDrawn())
  309. //Try locking the canvas for pixel editing on surface
  310. try
  311. {
  312. screen = getHolder().lockCanvas();
  313. if (screen != null)
  314. synchronized (getHolder())
  315. {
  316. //Actual drawing
  317. draw(screen);
  318. //Debug
  319. //screen.drawText("Number of threads: " +Thread.activeCount(), 100, 100, font);
  320. //screen.drawText("ms of this frame: " +(System.currentTimeMillis() -startTime), 100, 120, font);
  321. }
  322. } finally{
  323. //Draw changes
  324. if (screen != null)
  325. getHolder().unlockCanvasAndPost(screen);}
  326. //End Frame
  327. long endTime = System.currentTimeMillis();
  328. if (endTime -startTime < 1000/30)
  329. try { Thread.sleep(1000/30 -(endTime -startTime)); } catch (InterruptedException e){}
  330. } //While end
  331. } //run() end
  332. }