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]

unresolved android.opengl.ETC1

unresolved problem ?

import android.opengl.ETC1;
import android.opengl.ETC1Util;

only available in android 2.2 above.

Mencoba untuk Fokus

Fokus dalam bekerja bukan lah yang mudah, dan memerlukan banyak latihan untuk bisa benar-benar fokus. Terutama bagi kita yang bekerja menggunakan komputer dan [apalagi] yang terhubung dengan internet. Sangat banyak gangguan dan pengalih perhatian baik yang kita sadari kalau itu memang gangguan dan yang tidak. Mengakses jejaring sosial [facebook, twitter, google+, friendster ] dalam bekerja, salah satu aktivitas yang merusak fokus .–Ya kita semua tau itu, tapi tetap saja dilakukan–. dan ada hal lain yang sepertinya bukan gangguan tapi kenyataannya gangguan, misalnya notifikasi e-mail, notifikasi ada update software, atau antivirus sedang meng-interupsi : “hey komputer mu ada virus beberapa menit lagi akan meledak” dan lainnya. Mungkin notifikasi dari e-mail yang memiliki intensitas paling tinggi. Walaupun e-mail ada hubungannya dengan pekerjaan tapi itu juga harus diwaspadai :p . Satu lagi yang pasti adalah gangguan adalah chatting, yah, selain e-mail ini adalah salah satu sarana kita berkomunikasi dengan cepat lewat jaringan, dan dengan mudah pula orang lain dari jarak jauh meng-interupt kita.

the art of focus

Lalu bagaimana solusinya? . cabut kabel jaringan , matikan antivirus, matikan automatic update, pakai headset dan bekerja!. hmm.. ya itu bukan solusi elegan. solusi yang lain: lakukan pengecekan secara berkala saja. misalnya kita bekerja dari jam 8 pagi sampai jam 5 sore, kita bisa mengecek email, mengupdate status twitter, dll jam 8 pagi, 12 siang dan 4 sore masing2 10-15 menit, dan selain waktu-waktu itu tutup semuanya jangan buka. Efek dari email mungkin kita akan telat dapat info :| , efek dari jejaring sosial : tidak ada, bahkan kalau kita tidak buka sama sekali juga tidak ada efeknya.hmm.. mungkin dianggap sedikit kuper :-) ) .

Kenapa harus fokus?, sederhana: kalau kita fokus kita akan bekerja dengan 100% dari kemampuan kita dan hasilnya sangat bagus dan cepat selesai.

Karena saya suka cepat !!

hmm, yah mungkin bukan hanya saya, tapi semua orang suka cepat dalam segala hal, tak terkecuali di komputer { apalagi } . Saya sedang membicarakan tampilan komputer. Kita bisa mengatur tampilan komputer kita, baik di Linux maupun Ms-Windows atau OS lain, dengan 2 batas : tampilan terindah dan tampilan tercepat. Beberapa orang memang suka hal-hal yang sangaaat indah, seperti tampilan GUI transparan, animasi button, dan lainnya (coba: win 7 tampilan terbaik, atau GNU/Linux Ubuntu tampilan terbaik). Dan ada orang yang suka super cepat!! :D . Super indah mengorbankan kecepatan dan super cepat mengorbankan keindahan. Bukankah komputer sekarang sudah sangat cepat. Hmm.. gimana kalo komputer yang super cepat itu di setting dengan tampilan super cepat, pasti itu yang paling cepat. Di Ms-Windows (XP di komputer ku, dan Win 7 di tempat kerja ) saya setting win classic theme, simple dan cepat. Di GNU/linux Ubuntu saya mencoba melakukan hal yang sama, namun belum nemu, karena walaupun saya setting dengan tanpa visual effect sama sekali, cursor masih menampakan shadow dan transparansi (argh.. pasti CPU ku perlu beberapa clock cycle untuk meng-generate itu).

Tapi saya tidak akan meng-implement pilihan “super cepat” di jalan raya, karena di situ teorinya beda :-| . Dan juga tidak “super cepat”, kalau hal itu mengurangi “kesempurnaan”.  Kesimpulan yang bisa ditarik (eh diketik) :  slow << fast << perfect .

love what you do

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

packing resources

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 :-D ) 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.

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 :D  >

Membuat Tetris

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:

Click untuk memperbesar

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.

post code: proximity game

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:

Click untuk memperbesar

Click untuk memperbesar

Screenshoot Gameplay:

Click untuk memperbesar

Click untuk memperbesar

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.

L.O.S.T / Coldplay

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
Follow

Get every new post delivered to your Inbox.