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