Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
28. June 2013

 

I mentioned a little while back that I ordered a 14” Razer and there were some shipping issues.  Anyways, it is here now and I’m loving it.  I’ve noticed in search logs I have people landing here because they searched for Razer Blade reviews.  I figured I would share my initial thoughts and impression for people interested in this unique laptop.

 

Apple was an obvious inspiration behind the Razer line of laptops.  In an interview with The Verge, Razer CEO Min-Liang Tan said:

I love Apple products," he says. "I think they do an incredible job in terms of industrial design. But, for us, it's also been an issue of creative professionals coming to us after Apple moved out of the 17-inch space."

 

I’ve owned several Apple products and I will admit this experience ( and price tag! Smile ) was by far the most Apple-like I’ve experienced on a non-Apple product, except perhaps my Sony Xperia phone.  It starts with the packaging experience on out.  My last Dell came in a brown box…  here is the Razer’s unboxing.

 

The box itself is actually a thing of beauty… not too many times I've even noticed the packaging of a product.

 

Box in the shipping packaging:

1

 

My new baby

2

 

The remaining contents…

3

Basically it’s the laptop, the power supply and a couple booklets and that’s it.  The box on the left is the power supply box, it’s pretty small.

 

That sexy box.

IMG_20130628_183329

 

Frankly that is what the Xbox 2 should have looked like!  I know at the end of the day this stuff doesn’t really matter.  It shows a level of pride though and an attention to detail.  Plus it makes you feel like a little kid on Christmas again… 

 

Now to the actual machine.  As a big part of this machine is it’s size, I’ll follow up with a number of close-up comparison shots, but for now, here it is relative to a 2012 Macbook Air, it’s Muse.

4

 

Now to the actual machine…  first off, it ships with Windows 8 and absolutely ZERO bloat.  Nothing at all.  What a refreshing experience not having to immediately re-install the operating system.  Drivers are all current and OS seems to be pretty up to date, it was pretty much a matter of start and go with this machine.

 

Specs

The machine itself has pretty solid technical specs:

Intel® Core™ i7-4702HQ Quad Core 2.2GHz / 3.2GHz (Base/Turbo)

8GB of RAM

GeForce GTX765M w 2GB DDR5

Integrated HD4600 GPU

14” 1600x900 matte display

256 GB SSD ( 128/512 available )

3USB 3 ports

 

The only thing that makes me a bit worried is the 8GB of RAM, it’s a tad on the light side by modern standards, but truth is, I rarely use that much even while compiling or doing 3D work.  The lack of ethernet kind of sucks, but the wireless works exceptionally well.  I don’t know if I can attribute that to Windows 8 or the chipset chosen, but the wifi performs MUCH better than all the other devices in my house. 

 

Performance and Benchmarks

One of the very first things I did was update the Windows Experience Index:

image

 

I’m kind of surprised by these scores across the board.  The Haswell Intel CPU scores respectably at 7.8, but the GeForce 675 GPU is easily the weakest link here.  It’s only about 20% higher than my 560M, that seems low to me.  I almost wonder if Optimus is to blame for the lowish Gaming Graphics score. The solid state drive scores respectably enough.

 

The GPU is a GeForce 765.  Here is how the GPU benchmarks relative to it’s peers according to notebookcheck.net

image

In terms of game frame rates, Bioshock Infinite clocks in at 80fps on high settings, while Crysis 3 manages 37.  In terms of actual frame rates, it seems to be about twice as fast as my Asus G53SX with a GeForce 560M.  It’s certainly not the fastest GPU, but its no slouch.  Its a fair bit faster than the GT 650M found in the MacBook Pro, the only comparable machine IMHO.

 

About Heat…

One big part about gaming laptops is managing heat.  On the whole the Razer does a pretty solid job.

This is the laptop temperatures reported at idle:

image

 

Now after an hour of gaming:

image

In terms of actual use, the wrist area gets slightly warm, ditto for the keyboard.  Not hot by any definition of the word.  The heat is almost entirely at the base of the screen, hot but not scalding to the touch.  Heat does vent out straight down at the screen bezel making it uncomfortable to game with it on your lap.  The bottom of the laptop itself is quite comfortable, except again right below the monitor.  It cools down very quickly, within 10 minutes or so of ending my gaming session, its back to normal temperatures.  If you game, do it on a table, not your lap.

By comparison to other machines, it handles heat much more quietly than my GeForce 560 equipped G53 and the head is much more localized.  It does however direct more of the heat downward than the G53.  The heat profile is actually very similar to the Macbook Air.  The Razer however is quiter than the Macbook and the surface area where heat is vented ( below the screen ) is much cooler on the Razer.  Over all I consider it pretty successful on heat venting, exceptionally successful on volume levels, but a bit disappointing about not being able to play with it on your lap comfortably, although that’s often the case with performance laptops, so I’m not surprised.

 

The Screen

The 1600x900 resolution seems about perfect for a 14” laptop.  I think 1080p would have been hard to read.  The viewing angle of the screen is exceptional, you can clearly read the screen from any angle from left to right.  Vertically its about +-30 degrees where visibility gets difficult.  The brightness is good, even using it outside in full daylight causes no issues.  The screen isn’t glossy at all, so I don’t have to look at my ugly mug’s reflection while typing.  The price though is a bit difficult…  When the screen is static it just looks…  muddy.  Like I can see small black spaces between pixels.  I am sure someone can describe it better, but when typing black text on a white background, it is very visible.  When gaming it isn’t.  It’s all a matter of opinion, but at the end of the day I like the performance of the screen ( brightness, viewing angle, etc… ) but I dont particularly like the look of it.

 

I’ve been asked to expand a bit on the matte effect on the screen.  I’ve tried to capture it as best as I can with a camera phone.  You may need to click the image to get the higher resolution version to clearly see.  The camera pic makes the effect look much much much much worse than it actually is.  The “grid” like effect is more like what you see in the top left or bottom right of the image below.  Again, the screen is nowhere near as bad as the screen actually is in use, but it gives you an idea of the grainy-ness that the matte screen adds.

 

The Battery

You may have heard the number 6 hours somewhere describing the Razer Blade’s battery life.  I honestly don’t think I could replicate this number… perhaps by turning the screen and CPU settings down to the lowest settings, turning off wifi and doing absolutely nothing for 6 hours it might work.  It’s only been a couple days so it’s hard to give exact figures, but my experience so far seem to indicate around 3.5-4.5 hours of casual use ( surfing, blogging, writing code ) on balanced power settings and screen at about medium brightness.  Gaming though is another story entirely.  I unplugged my laptop from 100% charged and played 15 minutes of MechWarrior Online.  This took 20% of my battery.  So basically you can expect about an hour of high CPU/GPU usage, kind of disappointing, but at the same time, pretty typical.  It’s better than my G53 which refuses to even run at full speed on battery and even still manages to get worse battery life than that!  Thankfully the power adapter for this thing is super light and small so you can carry it around with you.

 

The user wrecks over at this notebookreview.com thread just posted this video of a battery test:

 

The details were:

Airplane Mode
40% Brightness
Vlc Player using integrated GPU playing 720p Video.

 

The laptop lasted 3:47 minutes then shut down with 7% battery remaining.

Build Quality

 

It’s top notch, exactly what you would expect from a 2000$ laptop.  All the edges are solid, there is no flexing or mismatched edges, etc.  The hinge seems strong and the action is smooth.  The keyboard is excellent.  Keys are well sized, good action and feedback.  It’s a mini layout of course, so no page up/down, end, home, etc.  The trackpad is very responsive and feels solid as well.  The dedicated buttons are a nice option, you could actually game on this trackpad… poorly, but that’s still better than most trackpads.  It’s superior to the Macbook Air’s trackpad, which is shocking as it is an excellent trackpad.  The buttons though, they worry me.  If there is a weakpoint on this trackpad, it’s the buttons for sure.

 

I did run into a problem with the trackpad, I dont know if its a Windows 8 issue or a Razer issue.  It ships default with scrolling reversed, which is irritating as hell.  You have an option to turn it off in the touchpad software, unfortunately it only effects one of the scrolling settings.  For example, I had two finger scrolling and hotspot scrolling both enabled ( this is how it ships ).  When you set the flip option, it only applies to the hotspot scrolling.  Disable the hotspot setting and then the two finger touch scrolling will work once flipped.  Not a big deal for me as I only wanted two finger scrolling available anyway.

 

Conclusion

So, do I feel it was worth my 2 grand?  Yes, very much so.  It’s a fast capable machine and very portable.  The audio output from this thing is surprisingly good while the noise levels from fans is impressively low.  It gets hot while gaming, but in the right spots.  You don’t want to use this thing on your lap and game, but you don’t want to do that with most gaming laptops.  On a desk the heat is perfectly manageable, in fact, you barely notice it. 

I love the fact the machine shipped with no bloat.  There is no recovery disk/USB stick, which is a bit disappointing.  Losing 15GB of a 256GB drive to a recovery partition is a bitter pill to swallow, would be even harder if I ordered the 128GB model.

In terms of the hardware, it’s very well made, very solid with no flexing.  The lack of a ethernet port is disappointing but the wireless is rock solid.  The screen is effective but certainly doesn’t wow me, if that makes sense.

The machine is very one of a kind right now.  The size and performance combo currently cannot be matched, but you are paying a premium for that combination.  If you don’t need the performance, you can get comparably built machines much cheaper ( such as the MacBook Air, or some premium Ultrabook models ) but you wont get the performance to play modern games or running demanding applications.  You can certainly get higher performance ( but currently not much higher with laptops ) at a lower price… but these machines certainly push the definition of “portable”.  This is to say nothing about build quality… I’ve owned a number of laptops and this is easily has one of the highest build qualities I’ve seen.

 

 

Dimensions and comparisons

Given that the machines dimensions are a big part of it, here are a series of comparison shots relative to other laptops I currently own.  It gives you a pretty good idea of it’s size.

 

Here is the 13” 2013 Macbook Air stacked on top of the Razer, on top of a Dell Studio 17, on top of a 15” Asus G53SX:

11

 

Here are the Asus, Razer and Macbook Air from above:

12

 

Now here are the Razer and Macbook from the side.

15

Front:

13

Back:

14

 

I’m not sure I buy the claim it’s thinner at the thickest part than the MacBook Air.

Totally Off Topic

blog comments powered by Disqus

Month List

Popular Comments

LibGDX Tutorial 3: Basic graphics
Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
2. October 2013

 

This is the part people always find the most fun, the actual act of putting graphics up on screen.  Let’s start with about the simplest project that we can.

 

We are going to display this sprite (created in this tutorial):

jet

 

On screen.  One important thing to note, the above graphic is 512x256.  OpenGL in general and LibGDX in specific, require your image files to be in power of two dimensions.  This means your width and height are 2,4,8,16,32,64,128,256,512,1024,2048, etc… pixels in size.  Be sure to add this file to the assets\data folder in the android project before continuing.

 

Let’s jump right in with code:

 

package com.gamefromscratch.graphicsdemo;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class GraphicsDemo implements ApplicationListener {
    private SpriteBatch batch;
    private Texture texture;
    private Sprite sprite;
    
    @Override
    public void create() {        
        batch = new SpriteBatch();
        texture = new Texture(Gdx.files.internal("data/jet.png"));
        sprite = new Sprite(texture);
    }

    @Override
    public void dispose() {
        batch.dispose();
        texture.dispose();
    }

    @Override
    public void render() {        
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        
        batch.begin();
        sprite.draw(batch);
        batch.end();
    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }
}

 

And if you run it:

image

 

The image is drawn relative to the origin.  In the case of LibGDX (0,0) is the bottom left corner of the screen.

 

As to the code, there isn’t actually a ton new compared to the Hello World example in the previous tutorial.  The only new concepts are the Texture and the Sprite.  The texture represents the underlying OpenGL texture.  One important thing to keep in mind with Texture ( and other similar classes ) is they implement the Disposable interface.  This means when you are done with it, you have to call the dispose() method, or you will leak memory!  A Sprite holds the geometry and colour data of a texture, this means the positional data ( such as it’s X and Y location ) are stored in the Sprite.  We construct our texture by passing it’s path in, obtained in the same manner we access the font in the prior tutorial.  We then construct the Sprite by passing in our newly created texture.  There are other ways of creating Sprites, that we will see shortly.  Just like in the Hello World sample, we start a SpriteBatch, and draw our sprite to it using the draw() method.

 

Dynamic textures with Pixmap

 

Your Texture’s source doesn’t have to come from a file.  Here we are going to use the Pixmap class to create the texture’s source dynamically.

 

package com.gamefromscratch.graphicsdemo;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class GraphicsDemo implements ApplicationListener {
    private SpriteBatch batch;
    private Pixmap pixmap;
    private Texture texture;
    private Sprite sprite;
    
    @Override
    public void create() {        
        batch = new SpriteBatch();
        
        // A Pixmap is basically a raw image in memory as repesented by pixels
        // We create one 256 wide, 128 height using 8 bytes for Red, Green, Blue and Alpha channels
        pixmap = new Pixmap(256,128, Pixmap.Format.RGBA8888);
        
        //Fill it red
        pixmap.setColor(Color.RED);
        pixmap.fill();
        
        //Draw two lines forming an X
        pixmap.setColor(Color.BLACK);
        pixmap.drawLine(0, 0, pixmap.getWidth()-1, pixmap.getHeight()-1);
        pixmap.drawLine(0, pixmap.getHeight()-1, pixmap.getWidth()-1, 0);
        
        //Draw a circle about the middle
        pixmap.setColor(Color.YELLOW);
        pixmap.drawCircle(pixmap.getWidth()/2, pixmap.getHeight()/2, pixmap.getHeight()/2 - 1);
        
        
        texture = new Texture(pixmap);
        
        //It's the textures responsibility now... get rid of the pixmap
        pixmap.dispose();
        
        sprite = new Sprite(texture);
    }

    @Override
    public void dispose() {
        batch.dispose();
        texture.dispose();
    }

    @Override
    public void render() {        
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        
        batch.begin();
        sprite.setPosition(0, 0);        
        sprite.draw(batch);
        sprite.setPosition(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2);
        sprite.draw(batch);
        batch.end();
    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }
}

 

Once again, the code is remarkably similar to our prior example.  The biggest difference is instead of loading the textures image data from file, we create one dynamically using a Pixmap.  At the simplest, a pixmap can be thought of as a grid of pixel data in memory.  It contains a number of graphical functions, many of which we demoed above.  The drawing code is pretty well commented in terms of what it does, so I wont go into details here.  One very important detail though, in the modern GPU driven world, these kinds of per pixel operations are REALLY REALLY SLOW.  Generally you want to avoid them as much as possible. 

 

The only other thing of note in this example is the changes in the render() method.  Notice how the same sprite is drawn twice to the sprite batch?  Well this behaviour is perfectly OK, and has minimal performance overhead in doing so.  Sprite’s setPosition method is used to position a sprite, once again, (0,0) is the lower left hand corner of the screen by default.  The only other new code here is the Gdx.graphics.getWidth() and getHeight() method calls.  These return the window’s ( or Canvas in the case of HTML5 ) dimensions.  Of course in production code you would probably cache them locally instead of retrieving them every pass through the render loop.

 

TextureAtlas

 

Quite often you want to deal with a sprite sheet, which is a number of sprites combined together into a single image.  Such functionality is built into LibGdx.  The first thing you are going to need is a directory of images that are going to be combined into a sprite sheet.  Like this:

image

 

Open a command line or terminal window and run the following command:

java -cp gdx.jar;extensions/gdx-tools/gdx-tools.jar com.badlogic.gdx.tools.imagepacker.TexturePacker2 c:\tmp c:\tmp spritesheet
tmp

It looks more unwieldy than it is.  Basically you are running the TexturePacker2 class inside the gdx-tools jar.  The first parameter is the source directory, the second parameter is the destination direction and the final parameter is the filename to use.  It will automatically add the required file extensions.  This process will create two files, a .atlas file and a .png.  The atlas file is a text file describing how the sprites are laid out in the spritesheet image, with the images filename used as the key ( minus extension ), like so:

spritesheet.atlas:

spritesheet.png
format: RGBA8888
filter: Nearest,Nearest
repeat: none
0001
  rotate: false
  xy: 1, 651
  size: 192, 128
  orig: 192, 128
  offset: 0, 0
  index: -1
0002
  rotate: false

 

While the sprite sheet itself looks like this:

spritesheet

 

The spritepacker tool automatically pads the image out to be a power of 2 in size.  I’ve only scratched the very surface of what this tool can do.  You can set it to run as part of your build process, run if from code or within Eclipse or even run it at program run time. There are a wealth of options you can configure.  You can read much more about it right here.

 

So how do you actually use a texture atlas then?  It’s very simple, first copy the generated png and atlas file to your assets.  The following code shows how to use a TextureAtlas:

 

package com.gamefromscratch.graphicsdemo;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.utils.Timer;
import com.badlogic.gdx.utils.Timer.Task;

public class GraphicsDemo implements ApplicationListener {
    private SpriteBatch batch;
    private TextureAtlas textureAtlas;
    private Sprite sprite;
    private int currentFrame = 1;
    private String currentAtlasKey = new String("0001");
    
    @Override
    public void create() {        
        batch = new SpriteBatch();
        textureAtlas = new TextureAtlas(Gdx.files.internal("data/spritesheet.atlas"));
        AtlasRegion region = textureAtlas.findRegion("0001");
        sprite = new Sprite(region);
        sprite.setPosition(120, 100);
        sprite.scale(2.5f);
        Timer.schedule(new Task(){
                @Override
                public void run() {
                    currentFrame++;
                    if(currentFrame > 20)
                        currentFrame = 1;
                    
                    // ATTENTION! String.format() doesnt work under GWT for god knows why...
                    currentAtlasKey = String.format("%04d", currentFrame);
                    sprite.setRegion(textureAtlas.findRegion(currentAtlasKey));
                }
            }
            ,0,1/30.0f);
    }

    @Override
    public void dispose() {
        batch.dispose();
        textureAtlas.dispose();
    }

    @Override
    public void render() {        
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        
        batch.begin();
        sprite.draw(batch);
        batch.end();
    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }
}

 

Here is the HTML5 version of the above code:

 

 

As you can see, it’s remarkably consistent.  The majority of the code above is actually part of the demo related, as opposed to being part of using a TextureAtlas.  Instead the only import new code is:

batch = new SpriteBatch();
textureAtlas = new TextureAtlas(Gdx.files.internal("data/spritesheet.atlas"));
AtlasRegion region = textureAtlas.findRegion("0001");
sprite = new Sprite(region);

Just like working with a texture, but instead you load a TextureAtlas.  Then instead of assign the texture to the sprite, you use an AtlasRegion, which describes the coordinates of the individual sprite within the spritesheet.  You get the region by name by calling the findRegion() method and passing the key.  Remember this value is set by the file names of the source images.  The TextureAtlas needs to be dispose()’d or you will leak memory.

As you can see by the call:

sprite.setRegion(textureAtlas.findRegion(currentAtlasKey));

You can change the region within the sprite sheet that the sprite will refer to by calling setRegion().

 

The rest of the code simply positions and scales the sprite up 2.5x times.  We then schedule a Task using Timer.schedule().  This task will be called ever 30th of a second.  It simply changes the key we will use within the TextureAtlas.   In this case the files were named 0001.png, 0002.png, etc…  so we want a value between 0001 and 0020.  We then use this value to update the region the sprite refers to.  As a result every 30th of a second, the sprite moves on to the next frame of animation, rolling over when it gets to the end.

 

EDIT: I should state for the record, this is NOT how you would use a TextureAtlas to perform animation, this code was simply for demonstration purposes.  There are dedicated animation classes and we will cover them later on.

 

Be warned though, if you try to run this under GWT, you will see:

image

 

This is because the GWT compiler ( this has nothing to do with LibGDX ) doesn’t support String.format() for some reason.  If you want to run this example in a browser you can simply replace

currentAtlasKey = String.format("%04d", currentFrame);

With:

String base = new String();
        
        if(currentFrame >= 10)
            base = "00";
        else
            base = "000";
        
currentAtlasKey = base + currentFrame;

 

Now the HTML target should run just fine.

 

In the next part we will take a look at controlling input in LibGDX.

 

Configuring LibGDX to use GL 2

 

It was brought to my attention by Mario Zechner that LibGDX is not limited to power of 2 texture sizes.  That instead is an artefact of OpenGL ES 1.  If you run using OpenGL ES2 it will work fine.  That said, OpenGL and the underlying hardware still perform better if you stick to power of two.  If you want to use GL2, you set it during as part of the configuration process, we discussed briefly in the Hello World tutorial.  Simply set the useGL20 value to true in the configuration you pass in to your application listener.  Here for example is Main from the desktop project configured to use GL 2.

 

public class Main {
    public static void main(String[] args) {
        LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
        cfg.title = "graphicsdemo";
        cfg.useGL20 = true;
        cfg.width = 480;
        cfg.height = 320;
        
        new LwjglApplication(new GraphicsDemo(), cfg);
    }
}

 

Remember of course to configure this for all targets you are supporting.

 

EDIT:

12/18/2013 – It was pointed out to me that I didn’t include the atlas files, making this tutorial hard to follow along with.  I have included an archive of the data folder used for this example, you can download it here.

Programming , ,

blog comments powered by Disqus

Month List

Popular Comments