Xedithor: 2D Sprite Editor
I created 2D sprite editor. version 1.00 is released. :) .
here is first shoot video: [please see full screen, I think youtube edit my video ]
Creating animation: [HD video]
I created 2D sprite editor. version 1.00 is released. :) .
here is first shoot video: [please see full screen, I think youtube edit my video ]
Creating animation: [HD video]
unresolved problem ?
import android.opengl.ETC1;
import android.opengl.ETC1Util;
only available in android 2.2 above.
learn many thing from Steve Jobs.
“Your work is going to fill a large part of your life, and the only way to be truly satisfied is to do what you believe is great work. And the only way to do great work is to love what you do. If you haven’t found it yet, keep looking. Don’t settle. As with all matters of the heart, you’ll know when you find it. And, like any great relationship, it just gets better and better as the years roll on. So keep looking until you find it. Don’t settle.”
– Stanford commencement speech 2005
Jika kita memperhatikan secara seksama semua program-program atau game yang tidak trivial (yang serius) selalu memproteksi resources/sumber daya yang digunakan. Resources disini maksudnya file-file yang berguna untuk game/program, misalnya library, gambar, sound, config file, text file, dan lainnya. Tujuannya jelas, agar tidak mudah diubah/dimodifikasi oleh user, atau setidaknya kalau pun user bisa mengubah , itu tidak dilakukan secara mudah. (ya, tidak ada yang 100 % aman di dunia komputer ). Dari apa yang saya lihat di folder data dari program dan games yang ter-install di komputer, ada macam-macam teknik untuk memproteksinya, ada yang hanya mengubah ekstensi file, (misalnya file : gambar.jpg menjadi blablabla.dll ), melakukan enkripsi dan mengkompress file, dan ada juga yang menjadikan seluruh resources menjadi 1 file besar, misalnya data.pak . Bagaimana kalau ingin membuat proteksi semacam itu? . Saya ingin mencobanya disini, tidak perlu menulis program dari scratch, cukup menggunakan library yang sudah ada. Zlib (library kompres-dekompresi yang popular se-antero internet
) dan C++ Boost adalah pilihan yang menarik. Dengan meng-kompresi data, kita tidak hanya membuat data tersebut tidak mudah di hack tapi juga membuat ukuran menjadi kecil a.k.a menghemat space.
Saya akan membuatnya sederhana. Ada 2 hal yang jelas : [1] program yang melakukan packing, dan [2] data yang terpacking bisa dibaca ulang oleh program yang akan menggunakan data tersebut. Daripada menjadikan beberapa file menjadi 1 file besar, saya lebih memillih mem-packing beberapa file dari sebuah folder (dan sub folder didalam-nya) kedalam 1 folder besar. Untuk mempermudah pembacaan dan peng-organisasian, dari segi pembaca data yang sudah di pack , “data” seolah-olah masih berada di folder sebelum dipack ( tidak membaca dari 1 folder ) . Untuk itu saya akan menyimpan informasi file-file tersebut kedalam 1 file berformat biner, yang nantinya bisa dibaca ulang.
Hmm.. so, here we go, berikut program test-nya: ( klik untuk ekspand source)
// test: packing-unpacking files
// @ edi ermawan , 20 Sept 2011
#include <iostream>
#include <vector>
#include <string>
#include "boost/filesystem.hpp"
#include <fstream>
#include "infdef.h"
using std::fstream;
using namespace boost::filesystem;
namespace xediconst
{
const std::string FileNameIdent ="data";
const std::string FileNameIdentExt =".pak";
const int max_path_str = 200;
}
using namespace xediconst;
class FileInfo
{
public:
FileInfo()
{
}
FileInfo(const std::string& str): mFileID(mLastFileID++)
{
const char *pC = str.data();
int length = str.size();
strncpy( mFileName, pC, length );
mFileName[length]='\0';
}
~FileInfo()
{
};
void setFileInfo(const int id,const std::string& str)
{
mFileID=id;
const char *pC = str.data();
int length = str.size();
strncpy( mFileName, pC, length );
mFileName[length]='\0';
};
int getFileID()
{
return mFileID;
};
std::string getFileName()
{
return mFileName;
};
public:
static int mLastFileID;
private:
int mFileID;
char mFileName[xediconst::max_path_str];
};
int FileInfo::mLastFileID=0;
//use boost
bool GetAllFiles(const path& dir_path,std::vector<FileInfo*>& list)
{
if ( !exists( dir_path ) )
return false;
directory_iterator end_itr;
for ( directory_iterator itr( dir_path ); itr != end_itr; ++itr )
{
if ( is_directory(itr->status()) )
{
GetAllFiles( itr->path(),list);
}
else
{
list.push_back(new FileInfo(itr->path().string()));
}
}
return true;
}
void SaveFile(std::vector<FileInfo*>& listFiles,const std::string& nameFile)
{
std::string nameFile2=nameFile+"\\"+FileNameIdent+FileNameIdentExt;
fstream fileOut(nameFile2.c_str(),std::ios::out|std::ios::binary);
std::cout<<" Saving... "<<nameFile<<std::endl;
if(!fileOut)
{
std::cout<<"Error saving file."<<std::endl;
return;
}
int i=0;
for(std::vector<FileInfo*>::iterator it=listFiles.begin();
it!=listFiles.end();it++)
{
fileOut.seekp( (i++) * sizeof(FileInfo) );
const char* c=reinterpret_cast<const char*>(*it);
fileOut.write(c,sizeof(FileInfo));
}
fileOut.close();
}
void ReadFiles(std::vector<FileInfo*>& listFiles,const std::string& nameFile)
{
std::string nameFile2=nameFile+"\\"+FileNameIdent+FileNameIdentExt;
fstream fileIn(nameFile2.c_str(),std::ios::in | std::ios::binary);
std::cout<<"Reading... "<<nameFile<<std::endl;
if(!fileIn)
{
std::cout<<"Error reading file."<<std::endl;
return;
}
FileInfo* temp=new FileInfo();
fileIn.read(reinterpret_cast<char*>(temp),sizeof(FileInfo));
while(fileIn && !fileIn.eof())
{
listFiles.push_back(temp);
temp=new FileInfo();
fileIn.read(reinterpret_cast<char*>(temp),sizeof(FileInfo));
}
fileIn.close();
}
//compress-decompress : use zlib
void CompressFiles(std::vector<FileInfo*>& listFiles,const std::string& nameFile)
{
FILE *file_in;
FILE *file_out;
for(std::vector<FileInfo*>::iterator it=listFiles.begin();
it!=listFiles.end();it++)
{
std::string nameIn=(*it)->getFileName();
char c[30];
itoa((*it)->getFileID(),c,10);
std::string nameOut=nameFile+"\\"+FileNameIdent+c+FileNameIdentExt;
std::cout<<"File: "<<nameIn<<" Compressed to :"<<nameOut<<std::endl;
file_in=fopen(nameIn.c_str(),"r+b");
file_out=fopen(nameOut.c_str(),"w+b");
int ret = def(file_in, file_out, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK)
{
zerr(ret);
}
fclose(file_in);
fclose(file_out);
}
}
void DecompressFiles(std::vector<FileInfo*>& listFiles,const std::string& nameFile)
{
FILE *file_in;
FILE *file_out;
for(std::vector<FileInfo*>::iterator it=listFiles.begin();
it!=listFiles.end();it++)
{
std::string nameOut=(*it)->getFileName();
char c[30];
itoa((*it)->getFileID(),c,10);
std::string nameIn=nameFile+"\\"+FileNameIdent+c+FileNameIdentExt;
std::cout<<"File: "<<nameIn<<" Extracted to :"<<nameOut<<std::endl;
file_in=fopen(nameIn.c_str(),"r+b");
file_out=fopen(nameOut.c_str(),"w+b");
int ret = inf(file_in, file_out);
if (ret != Z_OK)
{
zerr(ret);
}
fclose(file_in);
fclose(file_out);
}
}
int main(int argc,char** argv)
{
if(argc<3)
{
std::cout<<"Usage: xedicompress -P RelativePathSrc RelativePathDest"<<std::endl;
std::cout<<"Usage: xedicompress -UP RelativePathDest"<<std::endl;
std::cout<<"Relative path from this app."<<std::endl;
return 0;
}
if (strcmp(argv[1], "-UP") == 0)
{
std::cout<<" Unpacking Files . . ."<<std::endl;
///path presult;
std::vector<FileInfo*>listFiles_2;
//read list of file from data.pak
ReadFiles(listFiles_2,argv[2]);
//after get list of files, then extract them.
DecompressFiles(listFiles_2,argv[2]);
}
else if (strcmp(argv[1], "-P") == 0)
{
std::cout<<" Packing Files . . ."<<std::endl;
path presult;
std::vector<FileInfo*>listFiles;
//get all files from specified path, save it into vector
GetAllFiles(argv[2],listFiles);
//save list of files in data.pak, as future reference for extracting
SaveFile(listFiles,argv[3]);
//compress all files
CompressFiles(listFiles,argv[3]);
}
else
{
std::cout<<"Usage: xedicompress -P RelativePathSrc RelativePathDest"<<std::endl;
std::cout<<"Usage: xedicompress -UP RelativePathDest"<<std::endl;
std::cout<<"Relative path from this app."<<std::endl;
return 0;
}
}
format penggunaan:
untuk Packing : xedicompress -P RelativePathSrc RelativePathDest
untuk Unpacking : xedicompress -UP RelativePathDest
contoh:
xedicompress -P ..\\test ..\\debug\\data
akan mengkompress seluruh file didalam folder test (dan subfolder di dalam test) ke folder \debug\data. Relative path terhadap folder dimana aplikasi berada.
xedicompress -UP ..\\debug\\data
Akan mendekompress seluruh file di debug\data ke folder asalnya.
#just_for_fun
boost ver 1.42
zlib ver 1.2.5
Pointer to function, pointer to function member of class.
#Cara 1 : Secara tradisional
Function pointer (pointer ke fungsi/penunjuk ke fungsi), dapat didefinisikan sebagai berikut:
(typeReturn*) functPointer(typeArgument,typeArgument2,..,typeArgumentN)
sebagai contoh, terdapat 2 fungsi dibawah ini:
void Function1()
{
cout<<" call Function1 Function1"<<endl;
}
int Function2(int a,int b)
{
return (a*b);
}
Contoh pemakaian function pointer dari 2 fungsi diatas, sebagai berikut:
void (*pf)(); // deklarasi pf=Function1; // assignment pf(); // pemanggilan int (*pf2)(int,int); // deklarasi pf2=Function2; // assignment int c=pf2(5,2); // pemanggilan
Lalu bagaimana kalau kita mau membuat function pointer yang menunjuk ke fungsi yang merupakan anggota dari sebuah class? . Deklarasi dan pemanggilannya agak berbeda, seperti contoh kelas Test dibawah ini:
class Test
{
private:
void (Test::*pf1)(); // deklarasi
int (Test::*pf2)(int,int); // deklarasi
public:
Test()
{
pf1=&Test::Function1; //assignment
pf2=&Test::Function2; //assignment
};
~Test(){};
void Function1()
{
cout<<" call Function1 Function1 "<<endl;
};
int Function2(int a,int b)
{
cout<<" call Function2 Function2 "<<endl;
return (a*b);
};
void Function3()
{
(this->*pf1)(); //pemanggilan
int c=(this->*pf2)(2,9); //pemanggilan
cout<<" c value: "<<c<<endl;
};
};
Dengan sedikit memodifikasi function pointer di kelas Test diatas , kita bisa memakai array of function pointer to member class . Misal kita akan mengubah pf1 sebagai array dari function pointer.
Deklarasi, assignment, pemanggilan:
void (Test::*pf1)[10](); // deklarasi, jumlah element array=10
pf1[0]=&Test::Function10; //assignment
pf1[1]=&Test::Function11; //assignment
….
….
pf1[9]=&Test::Function12; //assignment
...
...
(this->*pf1)[index](); //pemanggilan , index= index yang di panggil
Dalam penggunaannya, array dari function pointer mungkin lebih sering digunakan.
#Cara 2 : Menggunakan Boost Library ( boost::function )
Pointer ke free function :
boost::function<void ()>funcp0; / akan menunjuk ke: void Function1() funcp0=&PrintFunction; funcp0(); boost::function<int (int,int)>funcp1; // akan menunjuk ke: int Function2(int a,int b) funcp1=&Function2; int h=funcp1(12,6); //maka h=72.
Untuk mengetahui function pointer yang menunjuk ke fungsi yang merupakan anggota dari sebuah class, function pointer di kelas Test diatas saya ubah sebagai berikut:
class Test2
{
private:
boost::function<void (Test2&)>pf1;
boost::function<int (Test2&,int,int)>pf2;
public:
Test2()
{
pf1=&Test2::Function1; //assignment
pf2=&Test2::Function2; //assignment
};
~Test2(){};
void Function1()
{
cout<<" call Function1 Function1 "<<endl;
};
int Function2(int a,int b)
{
cout<<" call Function2 Function2 "<<endl;
return (a*b);
};
void Function3()
{
pf1(*this); // pemanggilan
int c=pf2(*this,2,9); // pemanggilan
cout<<" c value: "<<c<<endl;
};
};
Dapat dilihat di kelas test diatas, yang berubah adalah deklarasi dan pemanggilan. Why boost? .it’s great. < mbebek
>
Tetris mungkin salah satu game puzzle yang sangat populer dan hampir dimainkan setiap orang. Game ini tersedia di berbagai device, mulai dari game boy yang dedicated untuk tetris, hand phone, komputer, Nitendo, dll. Dulu saat saya masih kecil, saya main tetris pertama kali di game boy milik teman saya. Perlu diketahui dulu tidak ada orang yang punya handphone di tempat tinggal saya.
.Mungkin terakhir kali saya aktif main tetris saat saya punya handphone modem Smart merk Huawey. Di situ disediakan game tetris. Saya hampir setiap saat memainkannya. Bahkan blok-blok tetris sampai terbawa mimpi. Serius !!. -hahaha-. Dan ternyata tetris memang bisa menyebabkan apa yang disebut Tetris Effect. Tetris Effect 2
Beberapa hari lalu, – tepatnya awal2 ramadhan ini – punya ide untuk buat Tetris versi saya sendiri. Ya mungkin semua programmer di dunia ini punya versi tetris mereka sendiri. Hehehe. Ok saya membuatnya dari scratch, dan harus buat dari kode saya sendiri. –kalau mencari source code tetris di google itu namanya bukan tetris versi saya dunk – . Agar tetris saya mendekati “standart tetris” saya melihat referensi di Wiki Tetris .– wow tetris punya wiki sendiri – . situs ini menjelaskan semua hal tentang tetris seperti: macam2 piece tetris, warna yang digunakan, system rotasi, bahkan system scoring yang digunakan.
Ok, setelah info tentang standart tetris didapat saat nya ngoding. Saya masih menggunakan SDL sebagai system drawing dan input handler . Dan tentu saya pakai C++. hal yang agak berbeda disini, mungkin, saya ingin menulis seluruh code game nya dalam 1 file saja: Main.Cpp. Kenapa? -tidak apa2 cuma pingin saja- . Jadi tidak ada game state.
Sesuai standar tetris terdapat 7 buah tetriminoes , dan setiap tetriminos saya representasikan sebagai array 2 dimensi 4×4. Misal tetriminoes type Z seperti berikut:
Tetriminoes tipe yang lain yaitu : tipe I, tipe J, tipe L, tipe O, tipe S, dan tipe T. Sedangkan board ukuran 10 x 20 juga di representasikan sebagai array 10 x 20.
Collision detection
Ceritanya setiap piece tetris akan bergerak jatuh, di waktu t, dan mempunyai posisi x dan y reletif terhadap board. Karena ukuran board 10 x20, maka maks X: 10 dan maks Y: 20. Setiap akan bergerak turun, di cek apakah terjadi collision atau tidak. Pengecekan dilakukan dengan mendetek apakah di posisi X, Y tersebut ada array bernilai 1 di array board 10×20 dengan meng-iterasi matrik 4×4 sesuai tipe tetriminoes.
Versi pertama yang sudah bisa dimainkan sebagai berikut:
Ukuran board 10×20, seperti standart tetris. Untuk warna saya tidak mengikuti standart.
Info project : language: C++, input and painting handler : SDL, graphics editing : Adobe Photosop
Source Code ( SVN checkout ) https://tetrisonyx.googlecode.com/svn/trunk
Binary version 1.00 win32 win xp,win 7 : https://tetrisonyx.googlecode.com
# Keyword: simple SDL game, game C/C++, game sederhana SDL, C/C++, Tetris.
Berawal dari (May 17, 2011 : from this post ) saya upload hasilnya disini . Untuk sekarang hanya bisa play dengan komputer. Play dengan teman di LAN belum saya implementasikan.
Screenshoot Main Menu:
Screenshoot Gameplay:
Source code (SVN check out) :
https://proximity-game-clone.googlecode.com/svn/trunk
Untuk binary and source code download :
http://code.google.com/p/proximity-game-clone/
# Keyword: simple SDL game, game C/C++, game sederhana SDL, C/C++, puzzle.
Just because I'm losing Doesn't mean I'm lost Doesn't mean I'll stop Doesn't mean I would cross Just because I'm hurting Doesn't mean I'm hurt Doesn't mean I didn't get What I deserved No better and no worse I just got lost Every river that I tried to cross Every door I ever tried was locked Ohhh and I'm... Just waiting 'til the shine wears off You might be a big fish In a little pond Doesn't mean you've won 'Cause a long may come A bigger one And you'll be lost Every river that you tried to cross Every gun you ever held went off Ohhh and I'm... Just waiting until the firing stopped Ohhh and I'm... Just waiting 'til the shine wears off Ohhh and I... Just waiting 'til the shine wears off Ohhh and I.. Just waiting 'til the shine wears off Lyric: Lost / Coldplay