How can I use lua to create levels and maps in cocos2d - cocos2d-iphone

I have this idea, where I want to use lua to create my levels, and the maps inside those levels. I want to simply and explicitly be able to manipulate data and add new levels as buy ins in the app store. How can I use lua to create maps and levels inside those maps? Does lua support OOP so I can make a base Map "class" and a base Level "class" or do I need to hardcode everything? I know for a fact that angry birds uses lua, so can I?
Any directions or samples are much appreciated. Thanks.

Lua does not support classes directly (although there are some libraries which offer class-like functionality), instead it uses data structures called tables. Tables are very versatile because they can contain strings, numbers, functions and other tables.
The big benefit of Lua is that it is scripted, so it can be downloaded as a file and run while the compiled game is running. Here's a possible example of level stored in a .lua file:
return {
name = 'Example level',
score = 80,
map = {
height = 8,
width = 8,
data = 'sssssssssoooooossoooooossoooooossoooooossoooooossbooooesssssssss'
},
ondraw = function (self)
drawmap(self.map)
drawscore(self.score)
end
}
Another feature which you may find useful are metatables. They sort-of allow inheritance to be used with tables. You can read more about implementing classes with metatables here: http://lua-users.org/wiki/SimpleLuaClasses

Related

Is there any way to define methods for data model when using FMPP?

I want to add methods to my datamodel so I need a way to specify them inside my tdd data file(s).
For example having a tdd data file containing two scalars :
a: 1
b: 1
I would like to add a method area which multiplies them.
Is this even possible and if so how do I achieve this?
So let's say you have MyUtils that has a foo() and a bar() methods, and you want to access those in the templates.
You can add an arbitrary Java objects to the model using the eval data loader in data, like myUtils: eval('new com.example.MyUtils()'). Then you can issue myUtils.foo() in the templates. But, you wanted to add the methods at top level. That's also possible. Both in eval and in a custom DataLoader (whichever you want to use) you have access to engine, the fmpp.Engine object. And then you can pull this trick:
// Note: In case you are using eval, use Java 1.2 syntax (no generics).
TemplateHashModel myUtilsModel = (TemplateHashModel) engine.wrap(new MyUtils());
Map<String, TemplateModel> myUtilsMethodModels = new HashMap<>();
myUtilsMethodModels.put("foo", myUtilsModel.get("foo"));
myUtilsMethodModels.put("bar", myUtilsModel.get("bar"));
return myUtilsMethodModels;
Then you add that Map to data without a name. (If you add a Map to data without a name, its keys become top-level variables.)
Certainly it can be polished to be nicer, like find methods you want automatically, etc. Plus I did not try this above (so typos are possible). But this is the basic idea. (I guess it would be practical if FMPP had a data loader that loads the static methods of a class... But, right now it doesn't have that.)

Please explain the Repository-, Mapping-, and Business-Layer relations and responsibilities

I've been reading a lot about this stuff and I am currently in the middle of the development of a larger web-application and its corresponding back-end.
However, I've started with a design where I ask a Repository to fetch data from the database and map it into a DTO. Why DTO? Simply because until now basically everything was simple stuff and no more complexity was necessary. If it got a bit more complex then I started to map e.g. 1-to-n relations directly in the service layer. Something like:
// This is Service-Layer
public List<CarDTO> getCarsFromOwner(Long carOwnerId) {
// Entering Repository-Layer
List<CarDTO> cars = this.carRepository = this.carRepository.getCars(carOwnerId);
Map<Long, List<WheelDTO>> wheelMap = this.wheelRepository.getWheels(carId);
for(CarDTO car : cars) {
List<WheelDTO> wheels = wheelMap.get(car.getId());
car.setWheels(wheels);
}
return cars;
}
This works of course but it turns out that sometimes things are getting more complex than this and I'm starting to realize that the code might look quite ugly if I don't do anything about this.
Of course, I could load wheelMap in the CarRepository, do the wheel-mapping there and only return complete objects, but since SQL queries can sometimes look quite complex I don't want to fetch all cars and their wheels plus taking care of the mapping in getCars(Long ownerId).
I'm clearly missing a Business-Layer, right? But I'm simply not able to get my head around its best practice.
Let's assume I have Car and a Owner business-objects. Would my code look something like this:
// This is Service-Layer
public List<CarDTO> getCarsFromOwner(Long carOwnerId) {
// The new Business-Layer
CarOwner carOwner = new CarOwner(carOwnerId);
List<Car> cars = carOwner.getAllCars();
return cars;
}
which looks as simple as it can be, but what would happen on the inside? The question is aiming especially at CarOwner#getAllCars().
I imagine that this function would use Mappers and Repositories in order to load the data and that especially the relational mapping part is taken care of:
List<CarDTO> cars = this.carRepository = this.carRepository.getCars(carOwnerId);
Map<Long, List<WheelDTO>> wheelMap = this.wheelRepository.getWheels(carId);
for(CarDTO car : cars) {
List<WheelDTO> wheels = wheelMap.get(car.getId());
car.setWheels(wheels);
}
But how? Is the CarMapper providing functions getAllCarsWithWheels() and getAllCarsWithoutWheels()? This would also move the CarRepository and the WheelRepository into CarMapper but is this the right place for a repository?
I'd be happy if somebody could show me a good practical example for the code above.
Additional Information
I'm not using an ORM - instead I'm going with jOOQ. It's essentially just a type-safe way to write SQL (and it makes quite fun using it btw).
Here is an example how that looks like:
public List<CompanyDTO> getCompanies(Long adminId) {
LOGGER.debug("Loading companies for user ..");
Table<?> companyEmployee = this.ctx.select(COMPANY_EMPLOYEE.COMPANY_ID)
.from(COMPANY_EMPLOYEE)
.where(COMPANY_EMPLOYEE.ADMIN_ID.eq(adminId))
.asTable("companyEmployee");
List<CompanyDTO> fetchInto = this.ctx.select(COMPANY.ID, COMPANY.NAME)
.from(COMPANY)
.join(companyEmployee)
.on(companyEmployee.field(COMPANY_EMPLOYEE.COMPANY_ID).eq(COMPANY.ID))
.fetchInto(CompanyDTO.class);
return fetchInto;
}
Pattern Repository belongs to the group of patterns for data access objects and usually means an abstraction of storage for objects of the same type. Think of Java collection that you can use to store your objects - which methods does it have? How it operates?
By this defintion, Repository cannot work with DTOs - it's a storage of domain entities. If you have only DTOs, then you need more generic DAO or, probably, CQRS pattern. It is common to have separate interface and implementation of a Repository, as it's done, for example, in Spring Data (it generates implementation automatically, so you have only to specify the interface, probably, inheriting basic CRUD operations from common superinterface CrudRepository).
Example:
class Car {
private long ownerId;
private List<Wheel> wheels;
}
#Repository
interface CarRepository extends CrudRepository<Car,Long> {
List<Car> findByOwnerId(long id);
}
Things get complicated, when your domain model is a tree of objects and you store them in relational database. By definition of this problem you need an ORM. Every piece of code that loads relational content into object model is an ORM, so your repository will have an ORM as an implementation. Typically, JPA ORMs do the wiring of objects behind the scene, simpler solutions like custom mappers based on JOOQ or plain JDBC have to do it manually. There's no silver bullet that will solve all ORM problems efficiently and correctly: if you have chosen to write custom mapping, it's still better to keep the wiring inside the repository, so business layer (services) will operate with true object models.
In your example, CarRepository knows about Cars. Car knows about Wheels, so CarRepository already has transitive dependency on Wheels. In CarRepository#findByOwnerId() method you can either fetch the Wheels for a Car directly in the same query by adding a join, or delegate this task to WheelRepository and then only do the wiring. User of this method will receive fully-initialized object tree. Example:
class CarRepositoryImpl implements CarRepository {
public List<Car> findByOwnerId(long id) {
// pseudocode for some database query interface
String sql = select(CARS).join(WHEELS);
final Map<Long, Car> carIndex = new HashMap<>();
execute(sql, record -> {
long carId = record.get(CAR_ID);
Car car = carIndex.putIfAbsent(carId, Car::new);
... // map the car if necessary
Wheel wheel = ...; // map the wheel
car.addWheel(wheel);
});
return carIndex.values().stream().collect(toList());
}
}
What's the role of business layer (sometimes also called service layer)? Business layer performs business-specific operations on objects and, if these operations are required to be atomic, manages transactions. Basically, it knows, when to signal transaction start, transaction commit and rollback, but has no underlying knowledge about what these messages will actually trigger in transaction manager implementation. From business layer perspective, there are only operations on objects, boundaries and isolation of transactions and nothing else. It does not have to be aware of mappers or whatever sits behind Repository interface.
In my opinion, there is no correct answer.
This really depends upon the chosen design decision, which itself depends upon your stack and your/team's comfort.
Case 1:
I disagree with below highlighted sections in your statement:
"Of course, I could load wheelMap in the CarRepository, do the wheel-mapping there and only return complete objects, but since SQL queries can sometimes look quite complex I don't want to fetch all cars and their wheels plus taking care of the mapping in getCars(Long ownerId)"
sql join for the above will be simple. Additionally, it might be faster as databases are optimized for joins and fetching data.
Now, i called this approach as Case1 because this could be followed if you decide to pull data via your repository using sql joins. Instead of just using sql for simple CRUD and then manipulating objects in java. (below)
Case2: Repository is just used to fetch data for "each" domain object which corresponds to "one" table.
In this case what you are doing is already correct.
If you will never use WheelDTO separately, then there is no need to make a separate service for it. You can prepare everything in the Car service.
But, if you need WheelDTO separately, then make different services for each. In this case, there can be a helper layer on top of service layer to perform object creation. I do not suggest implementing an orm from scratch by making repositories and loading all joins for every repo (use hibernate or mybatis directly instead)
Again IMHO, whichever approach you take out of the above, the service or business layers just complement it. So, there is no hard and fast rule, try to be flexible according to your requirements. If you decide to use ORM, some of the above will again change.

When does having a service layer make no sense?

Having all your business logic in one place comes with various benefits. It makes your logic clean and easy to debug. However, I feel that it does not scale well under some circumstances.
For example,
class Book{
String a, b......z;
}
My book class has 26 fields ( a thru z). For searching alone, there are 2^26 possible ways to query.
If I were to write a service class (repository) for this :
interface BookRepo{
List<Book> findById(int id);
List<Book> findByA(String a);
List<Book> findTop10ByADescending(String a);
List<Book> findByBAndCAndDAnd....Z(String a, b, c,d, e....z);
....
}
As you can see, it is absurd since there are so many combinations of search variable possible, not to mention sorting, and paging variables that may come into the picture.
If my application is so flexible such that for a given "Resource", user can filter any field, sort by anything. Shouldn't I skip service layer completely?
I have tried writing a "generic" service layer, it is not easy in statically typed language. In addition, if your service layer now lets everything through, there is no point having it there.
your problem is not really related to existing vs missing a service layer. your problem is caused by bad data structure and/or repository design.
if you want to filter by all possible combinations of 26 letters then think about creating queries dynamically and/or make many-to-many relationship between letter and book rather than having 26 fields inside a book. then you will have constant and small number of repository methods and you can easily add new letters.
if your application doesn't need service layer then you don't have to add it. but if you don't have it and your application grows it's harder to spot the moment when it's needed. instead people tend to put service-logic into controllers and/or repositories. especially when you work in a team

How can I associate data - a string, integer or enum member - with a Gtk::ComboBoxText item?

I am using gktmm 3.0 on an Ubuntu 12.04 box with the default GCC toolchain.
In the C# world, the ComboBox class has a ComboxBox.item[n].value property, which allows you to associate each item in the comboBox with data.
I am looking for something similar in the Gtk::ComboBoxTextclass. How can I associate data - a string, integer or enum member for example - with a particular Gtk::ComboBoxTextitem?
I know that many frameworks provide a genericdata pointer on widgets for such use, as this is quite a common need.
Is there something in Gtk::ComboBoxText class or one of its parent classes that might allow me accomplish this, or do I need to set up such an association myself, using a map or other associative collection?
The Gtk::ComboBoxText append, insert() and prepend() methods allows you to specify an ID string as well as the human-visible text. For instance:
https://developer.gnome.org/gtkmm/stable/classGtk_1_1ComboBoxText.html#a19e80f4e451e23d2c00d3fb11023f9f2
But it would be clearer and more type-safe to use Gtk::ComboBox and define an actual underlying model that contains the associated data. This example uses an int, but you could use other types or use more columns:
https://developer.gnome.org/gtkmm-tutorial/stable/combobox-example-full.html.en

How would you support super-columns in the libQtCassandra library?

I wrote libQtCassandra and the current version does not support super-columns. One reason for not adding that support has been that it breaks the scheme used by the library to give users a way to use the array operator ([]) to access and write the data.
If you're not familiar, the library let's you create a "context" (a connection to a Cassandra cluster) and from that context you can write something like this:
// set value 123 in "column name" of "row key" of "column family":
context["column family"]["row key"]["column name"] = 123;
// retrieve that value:
int value = context["column family"]["row key"]["column name"];
So... very simple. However, if we introduce super-columns, we add one more array access which depends on whether there is a super-column or not. What would you do?
Would you use a function to access super columns?
context["column family"]["row key"].sc("super column")["column name"] = 123;
Or would you make the super column work seamlessly like the other parameters?
context["column family"]["row key"]["super column"]["column name"] = 123;
Obviously the system (column family) knows what's what. So it is easy to implement it either way, only it makes the library quite a bit more complicated to support the array syntax for super-columns.
I had another idea which was to add an object that could be used when specifying the row. But that looks rather ugly:
context["column family"][sc("row key", "super column")]["column name"] = 123;
This is easier to implement but doesn't look too good when you look at final code.
What would be a more stl or boost like approach to such a problem?
Seems like introducing supercolumn support would only continue to encourage the use of a deprecated feature. Use of alternatives such as composites are a better approach to solving problems that push people toward supercolumns. I'm not sure the effort wouldn't actually be a movement in the wrong direction. In the meantime, if people MUST access supercolumns from a C++ app, they can do so using Thrift.
So my suggestion would be to discuss a way to add composite support in libQtCassandra, since it doesn't appear to be there at the moment. This way we encourage users to make wiser data model choices by providing easier access to the correct constructs.