Commits

Ivan Vučica  committed de8c795

Added scene class to contain game logic and draw multiple pages. Added initialization of GNUstep. Preloading log.so as GNUstep now contains Android logging code. Added character movement that uses scene class.

  • Participants
  • Parent commits de1e9ff

Comments (0)

Files changed (8)

File IVNativeActivity.java

     File privateStorageDir = applicationContext.getFilesDir();
     String libPath = privateStorageDir.getAbsolutePath();
     */
+    System.loadLibrary("log");
     System.loadLibrary("objc");
     System.loadLibrary("gnustep-base");
     System.loadLibrary("CatchDroid");
 
 CFLAGS += -Ilibpng-android/jni
 
-OBJS=src/catchdroid.o src/Texture.o src/Asset.o src/Page.o src/Character.o
+OBJS=src/catchdroid.o src/Texture.o src/Asset.o src/Page.o src/Character.o src/Scene.o
 
 all: $(APKNAME).apk
 

File assets/pages/15-16

+00 08 09 10 11 12 00 00
+00 16 17 18 19 20 00 00
+00 00 00 01 00 00 00 00
+00 00 00 01 00 00 00 00
+00 00 00 01 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 02 02 02 02 00 00
+00 00 00 00 00 00 00 00 

File src/Character.m

       glTranslatef(0, -(1.0 - progress) * multiplier, 0);
       break;
       case 1: // face right
-      glTranslatef((1.0 - progress) * multiplier, 0, 0);
+      glTranslatef(-(1.0 - progress) * multiplier, 0, 0);
       break;
       case 2: // face down
       glTranslatef(0, (1.0 - progress) * multiplier, 0);
       break;
       case 3: // face left
-      glTranslatef(-(1.0 - progress) * multiplier, 0, 0);
+      glTranslatef((1.0 - progress) * multiplier, 0, 0);
       break;
     }
   }
 #import "Asset.h"
 
 #include <android/log.h>
-
 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
 
   BOOL success = [self loadFromFile: [NSString stringWithFormat: @"pages/%d-%d", pageX, pageY]];
   if (!success)
   {
-    [self release];
-    return nil;
+    NSString * repeatingTile = @"63 ";
+    NSString * map = [@"" stringByPaddingToLength:PAGE_WIDTH*PAGE_HEIGHT * [repeatingTile length] withString: repeatingTile startingAtIndex: 0];
+    success = [self loadFromString: map];
+    if (!success)
+    {
+      [self release];
+      return nil;
+    }
   }
-  LOGI("%g %g - %g %g - %g %g - %g %g", 
-      gridVertices[0], gridVertices[1],
-      gridVertices[2], gridVertices[3],
-      gridVertices[4], gridVertices[5],
-      gridVertices[6], gridVertices[7]);
 
   return self;
 }
 
 - (BOOL) loadFromFile: (NSString*) path
 {
-
   Asset * asset = [Asset assetWithPath: path];
   if (!asset)
   {
   }
 
   NSString * s = [[asset string] stringByReplacingOccurrencesOfString: @"\n" withString: @" "];
+  return [self loadFromString: s];
+}
+- (BOOL) loadFromString: (NSString*) s
+{
   NSArray * tiles = [s componentsSeparatedByString: @" "];
   int i = 0;
   for(NSString * tile in tiles)
               (2 * k + 1);
       _textureCoordinates[a] = (_tiles[i] % (TILESET_WIDTH) + textures[2*k + 0]) / ((GLfloat)TILESET_WIDTH);
       _textureCoordinates[b] = (_tiles[i] / (TILESET_WIDTH) + textures[2*k + 1]) / ((GLfloat)TILESET_HEIGHT); 
-
-      LOGI("%d,%d - vertex %d: into %d,%d go %g,%g", x, y, k, a, b, _textureCoordinates[a], _textureCoordinates[b]);
     }
 
     i++;
+#import <Foundation/Foundation.h>
+
+@class Character;
+
+@interface Scene : NSObject
+{
+  NSMutableDictionary * _pages;
+  int _playerX, _playerY;
+  Character * _player;
+
+  SEL _direction;
+}
+@property (retain) NSMutableDictionary * pages;
+@property (assign) int playerX;
+@property (assign) int playerY;
+@property (retain) Character * player;
+
+@property (assign) SEL direction;
+@end
+
+#import "Scene.h"
+#import "Page.h"
+#import "Character.h"
+
+#include <android/log.h>
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
+
+@implementation Scene
+@synthesize pages=_pages;
+@synthesize player=_player;
+@synthesize playerX=_playerX;
+@synthesize playerY=_playerY;
+@synthesize direction=_direction;
+- (id) init
+{
+  self = [super init];
+  if(!self) return nil;
+
+  _pages = [NSMutableDictionary new];
+  _player = [[Character alloc] initWithTexturePath: @"player.png"];
+
+  self.playerX = 16*8;
+  self.playerY = 16*8;
+
+  return self;
+}
+
+- (void) dealloc
+{
+  [_player release];
+  [_pages release];
+  [super dealloc];
+}
+
+- (void) movePlayerUp
+{
+  if(_player.progress < 1) return;
+  [_player setDirection: 0];
+  self.playerY--;
+}
+- (void) movePlayerRight
+{
+  if(_player.progress < 1) return;
+  [_player setDirection: 1];
+  self.playerX++;
+}
+- (void) movePlayerDown
+{
+  if(_player.progress < 1) return;
+  [_player setDirection: 2];
+  self.playerY++;
+}
+- (void) movePlayerLeft
+{
+  if(_player.progress < 1) return;
+  [_player setDirection: 3];
+  self.playerX--;
+}
+
+- (void) setPlayerX: (int)playerX
+{
+  _playerX = playerX;
+  _player.progress-=1.;
+  if(_player.progress < 0) _player.progress = 0;
+  _player.mapX = _playerX;
+}
+- (void) setPlayerY: (int)playerY
+{
+  _playerY = playerY;
+  _player.progress-=1.;
+  if(_player.progress < 0) _player.progress = 0;
+  _player.mapY = _playerY;
+}
+
+#define PAGE_WIDTH 8
+#define PAGE_HEIGHT 8
+- (void) draw
+{
+  int playerPageX = _playerX / PAGE_WIDTH;
+  int playerPageY = _playerY / PAGE_HEIGHT;
+
+  glPushMatrix();
+  [_player translateWithMultiplier: -1];
+  glTranslatef(-(_playerX % PAGE_WIDTH),
+               (_playerY % PAGE_HEIGHT),
+               0);
+  for(int i = -1; i <= 1; i++)
+  {
+    for(int j = -2; j <= 2; j++)
+    {
+      int currentPageX = playerPageX + i;
+      int currentPageY = playerPageY + j;
+      NSString * currentPage = [NSString stringWithFormat: @"%d-%d", currentPageX, currentPageY];
+      Page * page = [_pages objectForKey: currentPage];
+      if (!page)
+      {
+        page = [[[Page alloc] initWithPageX: currentPageX pageY: currentPageY] autorelease];
+        if(!page)
+          continue;
+        [_pages setObject: page forKey: currentPage];
+        if(![_pages objectForKey: currentPage])
+          LOGI("Caching the page failed?!");
+      }
+      
+      glPushMatrix();
+      glTranslatef(i * PAGE_WIDTH, -j * PAGE_HEIGHT, 0);
+      [page draw];
+      glPopMatrix();
+    }
+  }
+  glPopMatrix();
+  // for player character, not doing translation
+  // others would have: [ch translateWithMultiplier: 1];
+  // (to apply 'progress' animation)
+  [_player draw];
+}
+
+- (void) update: (double)dt
+{
+  [_player update: dt];
+  if(_direction)
+    [self performSelector: _direction];
+}
+@end
+

File src/catchdroid.m

 #import "Texture.h"
 #import "Page.h"
 #import "Character.h"
+#import "Scene.h"
 
 /**
  * Our saved state data.
 
     @private
     Texture * _controls;
-    Page * page;
-    Character * ch;
     double _previousFrameTime;
+    Scene * _scene;
 }
 -(int)setupDisplay;
 -(void)terminateDisplay;
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
 
-    page = [[Page alloc] initWithPageX: 16 pageY: 16];
-
     _controls = [Texture textureWithPath: @"controls.png"];
     [_controls retain];
 
-    ch = [[Character alloc] initWithTexturePath: @"player.png"];
+    _scene = [Scene new];
 
     //[self showToast: @"Tap to begin"];
 
 
     glMatrixMode(GL_MODELVIEW);
     glPushMatrix();
-    [ch translateWithMultiplier: -1];
-    [page draw];
+    [_scene draw];
     glPopMatrix();
-    glPushMatrix();
-    // for player character, not doing translation
-    // others would have: [ch translateWithMultiplier: 1];
-    [ch draw];
-    glPopMatrix();
-
     ////////////////////////
 
     glPushMatrix();    
       deltaT = 0.1;
 
     // update all objects
-    [ch update: deltaT];
+    [_scene update: deltaT];
   }
   _previousFrameTime = currentTime;
 
     _controls = nil;
     [ch release];
     ch = nil;
+    [_scene release];
+    _scene = nil;
 
     if (self->display != EGL_NO_DISPLAY) {
         eglMakeCurrent(self->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
         static const int MAXIMUM_TOUCHES = 2;
         switch(action)
         {
-          case AMOTION_EVENT_ACTION_POINTER_UP: 
-          case AMOTION_EVENT_ACTION_UP: 
+          case AMOTION_EVENT_ACTION_POINTER_DOWN:
+          case AMOTION_EVENT_ACTION_DOWN: 
           case AMOTION_EVENT_ACTION_MOVE: 
           { 
             int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) 
 
             float pressure = AMotionEvent_getPressure(event, index); 
 
-
-            if(y < 0.10)
-              LOGI("LEFT");
-            else
-
+            if(x / (float)width < 0.10)
+              [_scene setDirection: @selector(movePlayerLeft)];
+            else if(x / (float)width > 0.26)
+              [_scene setDirection: @selector(movePlayerRight)];
+            else if(y / (float)height < 0.72)
+              [_scene setDirection: @selector(movePlayerUp)];
+            else if(y / (float)height > 0.85)
+              [_scene setDirection: @selector(movePlayerDown)];
             LOGI("Engine %g %g action %d", x / (float)width, y / (float)height, action);
             break;
           }
+          case AMOTION_EVENT_ACTION_POINTER_UP: 
+          case AMOTION_EVENT_ACTION_UP: 
+            [_scene setDirection: NULL];
+            break;
           default:
           LOGI("New action");
         }
 
   (*env)->CallVoidMethod(env,toast,show);
 
+  (*env)->DeleteLocalRef(env, txt);
+
   (*vm)->DetachCurrentThread(vm);
 
 }
     // Make sure glue isn't stripped.
     app_dummy();
 
+    // Very low tech way to initialize the GNUStep multithreaded system
+    // TODOANDROID: isMainThread is false here we need to add a method to NSThread like GSSetThisThreadMainThread();
+    //NSThread* init = [[NSThread alloc] initWithTarget:nil selector:nil object:nil]; // cannot call before GSInitializeProcess()
+    //[init start];
+
+    // maybe we want AndroidCore_setMainThreadJNIEnv(env);
+
+    NSAutoreleasePool * arp = [NSAutoreleasePool new];
+
+    NSString * cmdline = [NSString stringWithContentsOfFile: [NSString stringWithFormat: @"/proc/%d/cmdline", getpid()]];
+    NSString * identifier = [[cmdline componentsSeparatedByString: @" "] objectAtIndex: 0];
+    NSString * home = [NSString stringWithFormat: @"/data/data/%@", identifier];
+    NSString * exe = [NSString stringWithFormat: @"%@/exe", home];
+    FILE * f = fopen([exe UTF8String], "w"); if(f) fclose(f);
+
+    NSString * path = [NSString stringWithFormat: @"PATH=%@", home];
+    NSString * home2 = [NSString stringWithFormat: @"HOME=%@", home];
+
+    const char* argv[1] = { [exe UTF8String] };
+    const char* env[4] = { "USER=android", [home UTF8String], [path UTF8String], NULL };
+    
+    GSInitializeProcess(1, argv, env);
+    //[[NSUserDefaults standardUserDefaults] readFromPath:userDefaultsPath()]; 
     LOGI("Preparing display");
     Engine * engine = [Engine new];
+    [arp release];
     app->userData = engine;
     app->onAppCmd = engine_handle_cmd;
     app->onInputEvent = engine_handle_input;
         int events;
         struct android_poll_source* source;
 
+        NSAutoreleasePool * arp = [NSAutoreleasePool new];
         // If not animating, we will block forever waiting for events.
         // If animating, we loop until all events are read, then continue
         // to draw the next frame of animation.
 
             [engine update];
         }
+        [arp release];
     }
 }