Saturday, October 6, 2012

Convert LibGDX .atlas files to Cocos2D .plist

Link:

https://github.com/thomas-villagers/gdxtococos2d


Sunday, May 27, 2012

Clojure macro for LibGDX input polling

A very simple macro:
(defmacro when-pressed
  ([key form]
  `(when (.isKeyPressed Gdx/input (. com.badlogic.gdx.Input$Keys ~key))
     ~form))
  ([key form & rest]
     `(do
        (when-pressed ~key ~form)
        (when-pressed ~@rest))))
example usage:
 (when-pressed LEFT  (do-something)
               RIGHT (do-something-different)
               SPACE ( ... )
               ...)
expands to:
user=> (pprint (macroexpand-1 '(when-pressed LEFT (do-something))))
(clojure.core/when
 (.isKeyPressed Gdx/input (. com.badlogic.gdx.Input$Keys LEFT))
 (do-something))
nil
or
user=> (pprint (macroexpand-1 '(when-pressed LEFT (do-something)
                                             RIGHT (do-something-else))))
(do
 (when-pressed LEFT (do-something))
 (when-pressed RIGHT (do-something-else)))
nil

Saturday, May 12, 2012

Android: A two column ListView with an ImageView

Struggling with ListViews and SimpleAdapters on Android, I came up with the following simple example of a ListView with two columns: an image and some text. In res/layout, create a xml list_item.xml for the listview items:
<?xml version="1.0" encoding="utf-8"?>
<!-- list_item.xml -->
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:paddingTop="4dip"
    android:paddingBottom="6dip"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#ffffff"
    android:orientation="horizontal">
    <ImageView android:layout_width="100px"
       android:layout_height="50px"
       android:layout_gravity="left"
       android:id="@+id/LOGO_CELL"
       />
    <TextView android:id="@+id/TEXT_CELL"
       android:layout_height="wrap_content"
       android:layout_width="wrap_content"
       android:textColor="#000000"
       android:layout_gravity="center"
       android:layout_weight="1"/>

</LinearLayout>

Add a ListView to main.xml main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
  <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Some Text"
      />
  <ListView  android:id="@+id/LISTVIEW"
      android:orientation="horizontal"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
   >
  </ListView>
</LinearLayout>

Finally, the code:
(ns com.example.android.ListExample 
  (:gen-class
   :extends android.app.Activity
   :exposes-methods {onCreate superOnCreate}
  (:import (android.app Activity)
           (android.os Bundle))))

(defn -onCreate  [this bundle]
    (.superOnCreate this bundle )
    (.setContentView this com.example.android.R$layout/main)
    (let [ids (int-array [com.example.android.R$id/LOGO_CELL
                          com.example.android.R$id/TEXT_CELL])
          names (into-array ["logo" "text"])
          thelist (java.util.ArrayList.
                   [{"logo" com.example.android.R$drawable/logo1 "text" "Text 1"}
                    {"logo" com.example.android.R$drawable/logo2 "text" "Text 2"}]
                   aa (android.widget.SimpleAdapter. this thelist
                                                     com.example.android.R$layout/list_item names ids)]
      (.setAdapter (.findViewById this com.example.android.R$id/LISTVIEW) aa)))
          
This will find the two pngs "logo1.png" and "logo2.png" in the res/drawable folders.

Thursday, March 1, 2012

LibGDX Triangle Example in Clojure

I started messing around with LibGDX with Clojure and came up with this translation of LibGDX's  example MyFirstTriangle.

There might be a bug in Clojure 1.3 with short arrays (?). While
float-array [0.5 0.5 0.5]
works,
short-array [0 1 2]
does not (exception).

(ns gdx1
  (:import (com.badlogic.gdx ApplicationListener Gdx)
           (com.badlogic.gdx.graphics GL10 Mesh VertexAttribute)
           (com.badlogic.gdx.backends.lwjgl LwjglApplication)))

(defn app-listener []
  (let [vertices (float-array [-0.5 -0.5 0 0.5 -0.5 0 0 0.5 0])
        triangles (into-array Short/TYPE [0 1 2])
        attrs (into-array VertexAttribute
         [(VertexAttribute.
           com.badlogic.gdx.graphics.VertexAttributes$Usage/Position
           3 "a_position")])
        mesh (ref nil)]
    (proxy [ApplicationListener] []
    (resize [w h] )
    (create []
      (let [m (doto (Mesh. true 3 3 attrs)
                (.setVertices vertices)
                (.setIndices triangles))]
      (dosync ( ref-set mesh m))))
    (render []
      (doto (Gdx/gl)
        (.glClear GL10/GL_COLOR_BUFFER_BIT))
     (doto @mesh
       (.render GL10/GL_TRIANGLES 0 3)))
    (pause [] )
    (resume [] )
    (dispose [] ))))

(defn App []
  (LwjglApplication. (app-listener) "My Game" 480 320 false))
This works fine in the repl. For Android, we would need to generate real classes, like so:
(ns net.thomas.android.MyFirstTriangle
  (:gen-class
   :extends com.badlogic.gdx.backends.android.AndroidApplication
   :exposes-methods {onCreate superOnCreate})
  (:import (android.os Bundle)
           (net.thomas.android Gdx1)
           (com.badlogic.gdx Gdx)
           (com.badlogic.gdx.backends.android AndroidApplication)))

(defn -onCreate [this bundle]
  (.superOnCreate this bundle)
  (.initialize this (Gdx1.) false))
and
(ns net.thomas.android.Gdx1
  (:gen-class
   :implements [com.badlogic.gdx.ApplicationListener]
  (:import (com.badlogic.gdx ApplicationListener Gdx)
           (com.badlogic.gdx.graphics GL10 Mesh VertexAttribute)))

(def vertices (float-array [-0.5 -0.5 0 0.5 -0.5 0 0 0.5 0]))
(def triangles (into-array Short/TYPE [0 1 2]))
(def mesh (ref nil))

(defn -resize [_ w h] )

(defn -create [_]
  (let [attrs (into-array VertexAttribute
                          [(VertexAttribute.
                            com.badlogic.gdx.graphics.VertexAttributes$Usage/Position
                            3 "a_position")])
        m (doto (Mesh. true 3 3 attrs)
            (.setVertices vertices)
            (.setIndices triangles))]
    (dosync (ref-set mesh m))))

(defn -render [_]
  (doto (Gdx/gl)
    (.glClear GL10/GL_COLOR_BUFFER_BIT))
  (doto @mesh
    (.render GL10/GL_TRIANGLES 0 3)))

(defn -pause [_] )
(defn -resume [_] )
(defn -dispose [_] )

Wednesday, February 29, 2012

How to use Apache Httpget in Clojure

Clojure's slurp function is great for quick retrieval of websites, but sometimes it's not enough and you'll get an 403 error.

As a quick fix I suggest using the Apache httpclient library. You will need httpclient-4.x.x.jar, httpcore-4.x.x.jar and commons-logging-1.x.x.jar in your classpath, which you can find here:
 The function http-get is a simple replacement for slurp. You can easily extend, e.g. adding timeouts, etc.


(ns apache-http
  (:import
   (org.apache.http.client ResponseHandler HttpClient methods.HttpGet)
   (org.apache.http.impl.client BasicResponseHandler DefaultHttpClient)))

(defn http-get [ url ]
  (let [client (DefaultHttpClient.)
        httpget (HttpGet. url)
        handler (BasicResponseHandler.)]
    (try 
      (let [body (.execute client httpget handler)]
        body)
      (catch Exception e (println e))
      (finally
        (println "shutdown connection")
        (.shutdown (.getConnectionManager client))
        )) ))

usage is simple:
(http-get "http://www.google.com")

Monday, February 27, 2012

A template for binomial coefficients in C++

Here's how you could implement a compile time calculation of
binomial numbers "n over k" in C++ with a template.


#ifndef BINOMIAL_HPP_INCLUDED

#define BINOMIAL_HPP_INCLUDED


template<int n, int k>
struct Binomial
{
  const static int value =  (Binomial<n-1,k-1>::value + Binomial<n-1,k>::value);
};

template<>
struct Binomial<0,0>
{
  const static int value = 1;
};

template<int n>
struct Binomial<n,0>
{
  const static int value = 1;
};

template<int n>
struct Binomial<n,n>
{
  const static int value = 1;
};

template<int n, int k>
inline int binomial()
{
  return Binomial<n,k>::value;
}

#endif


Now let's try it with a short main:
#include "Binomial.hpp"
#include <iostream>

int main()
{
  std::cout << "30 over 15: " << binomial<30,15>() << std::endl;
  return 0;
}
  

30 over 15: 155117520
It works! When it will break depends on your compiler. I used g++ 4.6.2

Android ListView Widget Example in Clojure

This is how you would implement the
Android ListViev Tutorial on Android dev in Clojure.
Follow the tutorial and the build instructions from Sattvik's Neko.

Replace the Java code with

( ns net.thomas.android.clojure.HelloListView
(:gen-class
   :extends android.app.ListActivity
   :exposes-methods {onCreate superOnCreate})
(:import android.util.Log)

(def STRINGS ["String1" "String2" "String3"])

(defn -onCreate  [this bundle]
    (.superOnCreate this bundle )
    (let [aa (android.widget.ArrayAdapter. 
 this net.thomas.android.clojure.R$layout/list_item STRINGS)]
      (.setListAdapter this aa)
      (let [lv (.getListView this)]
        (.setTextFilterEnabled lv true)
        (.setOnItemClickListener lv 
         (proxy  [android.widget.AdapterView$OnItemClickListener] []
           (onItemClick [parent view position id]
            (Log/d "CLOJURE" "CLICKED" ))
           ))
        )))


Use adb logcat and you should see the message when an item is clicked.

Clojure Falling Blocks Game

A game with falling blocks in Clojure :-)

load it in the repl and start with

(game)

This code is loosely based on the Snake example in the excellent book Programming Clojure by Stuart Halloway.

(ns titres
(:import (java.awt Color Dimension)
         (javax.swing JPanel JFrame Timer JOptionPane)
         (java.awt.event ActionListener KeyListener WindowAdapter)) )

(def frame-millis 60)
(def cell-size 40)
(def width 10)
(def height 15)
(def dirs { java.awt.event.KeyEvent/VK_LEFT [-1 0]
            java.awt.event.KeyEvent/VK_RIGHT [1 0] })
(def frames-to-drop 6)

(def blocks  [ '([0 0] [1 0] [0 1] [1 1]) '([0 0] [1 0] [2 0] [0 1])
               '([0 0] [1 0] [2 0] [2 1]) '([0 0] [1 0] [1 1] [2 1]) 
               '([0 0] [1 0] [2 0] [1 1]) '([1 0] [2 0] [0 1] [1 1])
               '([0 0] [1 0] [2 0] [3 0]) ] )
(def colors [(Color. 15 160 70)  (Color. 160 15 70) (Color. 15 70 160)
             (Color. 70 160 15) (Color. 70 15 160) (Color. 160 70 15) (Color. 160 70 160)] )

(defn make-block 
 ([n]
  { :location [0 0] 
    :body  ( blocks n ) 
    :color ( colors n )})
 ([] (make-block (rand-int (count blocks)))))

(defn point-to-screen-rect [pt] 
  (map #(* cell-size %) [(pt 0) (pt 1)  1 1]))

(defn fill-point [g pt color]
  (let [[x y width height] (point-to-screen-rect pt)]
  (.setColor g color)
  (.fillRect g x y width height)))

(defn paint-block [g {:keys [body location color]}]
  (doseq [point body]
    (fill-point g  (vec (map + point location)) color)))

(defn paint-stash [g stash] 
  (doseq [m stash]
    (fill-point g (key m) (val m)))) 

(defn insert-to-stash [stash {:keys [body location color] }]
  (let [body-shifted (map #(vec (map + location %)) body) ]
    (merge stash (zipmap body-shifted (repeat color)) )))

(defn hits-bottom? [{:keys [location body] }]
  (let [[x y] (map + location (apply map max body))]
    (= y height) ))

(defn collision? [stash {:keys [location body]} direction]
  (let [body-shifted (map #(vec (map + location direction %)) body) ]
    (some #(contains? stash %) body-shifted) ))

(defn hits-stash? [stash block]
  (collision? stash block [0 1]))
 
(defn delete-row [stash row]
  (let [new-stash (filter #(not= row ((key %) 1)) stash)
        new-stash-keys ( map #( cond (< (% 1) row) 
                                (vec (map + % [0 1])) 
    :else % ) (keys new-stash) ) ]
    (zipmap new-stash-keys (vals new-stash))  ))

(defn count-row [stash row]
  (count (filter #(= row (% 1)) (keys stash))) )

(defn delete-rows [stash row]
  (if (> row height) stash 
   (if (> (count-row stash row)  width) 
      (recur  (delete-row stash row) (inc row) )
      (recur  stash (inc row) ) 
   ) ))
       
(defn transpose-pt [pt height]
  [(- height (pt 1)) (pt 0) ])

(defn rotate-right [{:keys [body] :as block}]
  (let [[width height] (apply map max body)]
    (assoc block :body (map #(transpose-pt % height) body))))

(defn rotate-left [block]
  (rotate-right (rotate-right (rotate-right block))))

(defn move [{:keys [location] :as block} direction]
  (assoc block :location (vec (map + location direction))) )

(defn block-hits-border? [{:keys [body location] } newdir]
  (let [min_x (first (map + (vec (apply map min body)) newdir location)) 
        max_x (first (map + (vec (apply map max body)) newdir location)) ]
  (or (< min_x 0) (> max_x width)) ))

(defn adjust-border [{:keys [body location] :as block}]
  (let [offset (- width (first (map + (apply map max body) location)))]
   (cond (< offset 0) (move block [offset 0]) 
    :else block ) ))

(defn update-position [stash block newdir]
  (when-not (or (collision? stash @block newdir
    (block-hits-border? @block newdir) ) 
    (dosync (alter block move newdir)) ))

(defn update-drop [stash block]
  (when-not (collision? stash @block [0 1])    
    (dosync (alter block move [0 1])) ))

(defn update-rotation [f stash block]
  (let [shifted-block (adjust-border (f @block))]
    (when-not (collision? stash shifted-block [0 0])   
      (dosync (ref-set block shifted-block)) )))  

(defn update-stash  [stash block]
  (dosync (alter stash insert-to-stash block))
  (dosync (alter stash delete-rows 0)) ) 

(defn game-panel [frame block]
(let [framecounter (ref  0)
      stash (ref {})]
(proxy [JPanel ActionListener KeyListener] []  
  (paintComponent [g]
   (proxy-super paintComponent g)
   (paint-block g @block)
   (paint-stash g @stash)
  )
  (actionPerformed [e] 
   (dosync (alter framecounter inc))
   (when (= 0 (mod @framecounter frames-to-drop)) 
    (update-drop @stash block)
    (when (or (hits-stash? @stash @block) (hits-bottom? @block)) 
     (update-stash stash @block)
     (dosync (ref-set block (make-block)))))
    (.repaint this) )
  (keyPressed [e]       
   (let [key (.getKeyCode e)]
   (cond 
     (= key java.awt.event.KeyEvent/VK_UP)   (update-rotation rotate-right @stash block)
     (= key java.awt.event.KeyEvent/VK_DOWN) (update-rotation rotate-left  @stash block)
     :else 
     (update-position @stash block (dirs key)) ))  )
  (keyReleased [e])
  (keyTyped [e])
  (getPreferredSize []
    (Dimension. (* (inc width) cell-size)
                (* (inc height) cell-size)))
)))

(defn frame-closing [timer] (proxy [WindowAdapter] []
                (windowClosing [e] (do (println "stopped") (.stop timer)))))

(defn game[]
  (let [frame (JFrame. "Tetris")
 block (ref (make-block))
        panel (game-panel frame block)
        timer (Timer. frame-millis panel)]
  (doto panel
   (.setFocusable true)
   (.addKeyListener panel))
  (doto frame
   (.addWindowListener  (frame-closing timer))
   (.add panel)
   (.pack)
   (.setVisible true))
   (.start timer) [timer]))

Clojure Game of Life

This is a Conway's Game of Life in functional style written in Clojure.
You would start it in the repl as

 (game "GUN44.LIF")

where "GUN44.LIF" is a LIF file -- you can find LIF files all over the
internet, e.g. Paul Calahan's great collection
http://www.radicaleye.com/lifepage/


The lif reader demonstrates how to read and process a file in Clojure.



(ns gol
  (:import (java.awt Color Dimension)
           (javax.swing JPanel JFrame Timer JOptionPane)
           (java.awt.event ActionListener KeyListener WindowAdapter))
  (:use lif))

(def frame-millis 30)
(def cell-size 5)
(def width 250)
(def height 160)

(def glider ^ints #{ [1 0] [2 1] [0 2] [1 2] [2 2] })
(def gun ^ints (process-file "../../lifep/GUN44.LIF"))

(defn get-neighbors[ ^ints [ox oy] ]
  (for [x (range (- ox 1) (+ ox 2))
        y (range (- oy 1) (+ oy 2)) ]
    [x y] ))

(defn collect-neighbors [field]
  (distinct (mapcat get-neighbors field)))

(defn count-alive-neighbors [ ^ints field]
  (fn [ cell ] (count (filter field (get-neighbors cell) ))))

(defn survives? [field]
 (let [count-alive-neighbors (count-alive-neighbors field)]
  (fn [ cell ]
    (let [n (count-alive-neighbors cell)]
      (or (= n 3) (= n 4))))))

(defn birth? [field]
  (let [count-alive-neighbors (count-alive-neighbors field)]
    (fn [ cell ]
      (= 3 (count-alive-neighbors cell)))))

(defn apply-rules [filterfunc]
  (fn [ field ]
    (let [dead-cells (remove field (collect-neighbors field))
          survives?  (survives? field)
          birth?     (birth? field)]
      (set (concat
            (filterfunc survives? field)
            (filterfunc birth?    dead-cells))))))

(defn pfilter [pred list]
  (map second (filter first (pmap (fn [cell] [(pred cell) cell]) list))))

(def apply-rules-p (apply-rules pfilter))
(def apply-rules-n (apply-rules filter))

(defn update-field [field]
  (swap! field apply-rules-n))

(defn point-to-screen-rect [pt] 
  (map #(* cell-size %) [(pt 0) (pt 1)  1 1]))

(defn fill-point [^java.awt.Graphics g pt color]
  (let [[x y width height] (point-to-screen-rect pt)]
   (.fillRect g x y width height)))

(defn paint-game [^java.awt.Graphics g field]
  (let [center [(bit-shift-right width 1) (bit-shift-right height 1)]
        color (Color. 15 160 70)]
    (.setColor g color)
    (doseq [point field]
      (fill-point g (vec (map + center point)) color) )))

(defn game-panel [frame field]
(proxy [JPanel ActionListener KeyListener] []  
  (paintComponent [^java.awt.Graphics g]
   (proxy-super paintComponent g)
   (paint-game g @field))
  (actionPerformed [e]
    (.repaint this)
    (println "active cells:" (count @field))
    (time (update-field field)))
  (keyPressed [e] )
  (keyReleased [e])
  (keyTyped [e])
  (getPreferredSize []
    (Dimension. (* (inc width) cell-size)
                (* (inc height) cell-size)))
))

(defn frame-closing [timer] (proxy [WindowAdapter] []
  (windowClosing [e] (do (println "stopped") (.stop timer)))))

(defn game
  ([filename]
  (let [frame (JFrame. "Game of Life")
        field (atom (^ints process-file filename) )
        panel (game-panel frame field)
        timer (Timer. frame-millis panel)]
  (doto panel
   (.setFocusable true)
   (.addKeyListener panel))
  (doto frame
   (.addWindowListener  (frame-closing timer))
   (.add panel)
   (.pack)
   (.setVisible true))
  (.start timer) [timer]))
  ([] (game "../../lifep/GUN44.LIF")))


The lif reader:
(ns lif
  (:import (java.io BufferedReader FileReader))
  (:use  [clojure.string :only (split)]
         [clojure.java.io :only (reader)])
  )

(defn collect-data [[x y] line]
  (remove nil?  (map #(when (= %1 \*) [%2 y]) line (iterate inc x))))

(defn is-data? [line]
  (or (= \. (first line)) (= \* (first line))))

(defn char-to-long [c]
  (Long. (str c)))

(defn is-coords? [line]
  (let [tokens (split line #"\s")]
    (= "#P" (tokens 0))))

(defn get-coords [line]
  (let [tokens (split line #"\s")]
    [(char-to-long (tokens 1)) (char-to-long (tokens 2)) ]))

(defn process-lines [[x y] lines accu]
  (let [line (first lines)]
    (cond (empty? lines)  accu   
          (is-data? line)
          (recur [x (inc y)] (rest lines)
                 (concat accu (collect-data [x y] line)))
          (is-coords? line)
          (recur (get-coords line )(rest lines) accu)
          :else  (recur [x y] (rest lines) accu))))

(defn process-file [file-name]
  (with-open [rdr (reader file-name)]
    (set (process-lines [0 0]  (line-seq rdr) nil))))



Have fun!



update:

I cleaned the mess up a bit. Still not as concise as cgrand's solution. Hope I find the time to check it out and see if it's faster than mine.