분류 전체보기 (358)

안녕하세요~~ 케이치입니다~


오늘은 자바스크립트를 삽입하는 방법


자바스크립트 코드는 헤드, 바디 태그 안에 들어갈 수도 있고 두 태그 모두에 들어갈 수도 있고, 외부파일로 정의해서 include할 수도 있습니다. 각각 어떻게 하는지 한번 알아보죠. 


 <head> 태그 내의 JavaScript

사용자가 발생시키는 특정 이벤트에 대해서 자바스크립트가 동작을 해야한다면 헤드태그 안쪽에 코드를 삽입합니다.

 

<html>
<head>
<script type="text/javascript">
<!--
function sayHello() {
   alert("Hello World")
}
//-->
</script>
</head>
<body>
<input type="button" onclick="sayHello()" value="Say Hello" />
</body>
</html>

 

 

 <body> 태그 내의 JavaScript

웹페이지가 로드될 때 자바스크립트 코드에 의해서 어떤 내용물이 화면에 출력되어야 한다면 바디 태그 안에 스크립트를 넣어주세요. 이 경우에는 자바스크립트 코드로 정의된 함수는 가질 수 없습니다.

 

<html>
<head>
</head>
<body>
<script type="text/javascript">
<!--
document.write("Hello World")
//-->
</script>
<p>This is web page body </p>
</body>
</html>

 

결과는 아래처럼 보이겠죠?

 

Hello World
This is web page body

 

 

<body> 와 <head>에 동시에 쓰이는 JavaScript

 

<html>
<head>
<script type="text/javascript">
<!--
function sayHello() {
   alert("Hello World")
}
//-->
</script>
</head>
<body>
<script type="text/javascript">
<!--
document.write("Hello World")
//-->
</script>
<input type="button" onclick="sayHello()" value="Say Hello" />
</body>
</html>

 


외부 파일로 정의된 JavaScript

JavaScript를 좀더 확장해서 쓰려면 외부파일로 정의해서 쓰는 방법이 있습니다. 기능별로 파일을 분리해서 정리하면 관리하기가 편해지겠죠. 이건 뭐 어떻게 관리하느냐에 따라 달렸지만요 ㅋ 여러 페이지에서 동일한 스크립트를 사용해야 한다면 분리해서 사용하시는 것이 편리할겁니다.

자바스크립트 코드를 외부파일로 저장하려면 .js확장자를 사용합니다. 그리고 이 파일을 include하는 방법은 src속성을 이용해서 파일경로를 지정해주면 됩니다. 


<html>
<head>
<script type="text/javascript" src="filename.js" ></script>
</head>
<body>
.......
</body>
</html>

 

 

filename.js 

function sayHello() {
   alert("Hello World")
}

 

 

한번씩 다 해보시고 안된다 하시는게 있으시면 댓글로 질문 남겨주세요~ ^-^


이상 케이치였습니다~


즐프하세요~~ ^-^

 

Reference : http://www.tutorialspoint.com/javascript/javascript_placement.htm 

 


안녕하세요 케이치입니다.

오늘은 혹시나 있을지 모르는 자바스크립트 미지원 브라우저에 메시지를 띄워주는 것을 할겁니다.

자바스크립트 미지원 브라우저에 경고메시지 보내기

아래처럼 간단하게 <noscript> 태그를 사용하면 됩니다.

 

<html>
<body>

<script language="javascript" type="text/javascript">
<!--
   document.write("Hello World!")
//-->
</script>

<noscript>
  Sorry...JavaScript is needed to go ahead.
</noscript>
</body>
</html>

 

 

자바스크립트를 미지원하는 브라우저나 설정에서 막아놓은 경우에는 <noscript> 태그 내에 있는 메시지가 출력됩니다. 

 

안녕하세요 케이치입니다.

 

자바스크립트를 공부해볼까요?

 

자바스크립트는 기본적으로  <script>... </script>  태그를 사용합니다. 

자바스크립트 태그는 웹페이지 어디에다가 넣어도 큰 상관은 없지만 일반적으로는  <head> 태그내에서 사용됩니다. 

 

<script ...>
  JavaScript code
</script>

 

script 태그는 두가지 중요한 속성을 가집니다.

  • language: 스크립팅 언어가 뭔지를 지정해주는거죠. 우리는 자바스크립트를 배우니까 javascript 라고하면 됩니다. 최신 버전의 HTML이나 XHTML에서는 사용하지 않게될거라고 하네요. 저도 이제 막 자스 공부를 시작해서 확실치는 않습니다 ㅋㅋ 

  • type:  타입은 "text/javascript" 이 되어야 합니다.  

 

그래서 아래처럼 기본틀이 잡혀있어야 하는 거죠.

 

<script language="javascript" type="text/javascript">
  JavaScript code
</script>

 

나의 첫 자바스크립트

모든 프로그래밍 언어에서 "Hello World"는 기본이죠. 자스(자바스크립트를 줄임)를 이용해서 "안녕 세상아"를 출력해보도록 하겠습니다. 

<html>
<body>
<script language="javascript" type="text/javascript">
<!--
   document.write("Hello World!")
//-->
</script>
</body>
</html>

 

 자 위 소스를 보시면 자스코드를 넣어야 할 부분에 주석처리하는 태그를 추가로 넣었습니다. 이건 왜 넣었냐 하면말이죠. 브라우저가 자바스크립트를 지원하지 않을 경우에는 실행하지 말라는 의미입니다. 지원하지 않는 브라우저가 실행하려면 오류가 날테니 말이죠. "//-->"에서  "//" 는 Javascript에서 쓰는 주석문법입니다.

 document.write 가 하는 역할은 HTML문서에 스트링을 쓰는 것입니다. 이 함수는 text나 HTML또는 둘 다를 쓰기위해서 사용될 수 있습니다. 어쨌든 결과는 아래처럼 나와야겠죠?

 

Hello World!

 

 

 

이제 자바스크립트의 특징을 알아보도록 하겠습니다.

빈칸, 탭, 그리고 라인 브레이커는 무시합니다.

JavaScript 는 코드내에 존재하는 스페이스나 탭, 그리고 new lines 를 무시합니다.

따라서 원하는 대로 깔끔하게 코드를 정리할 수가 있겠죠??

세미콜론은 옵션입니다.

일반적으로 라인의 끝을 알려주는게 세미콜론이죠. C, Java 등등에서 모두 그렇게 쓰입니다. 하지만 자스에서는 아래처럼 써도 상관없습니다.  

<script language="javascript" type="text/javascript">
<!--
  var1 = 10
  var2 = 20
//-->
</script>

 

하지만 세미콜론을 쓰지 않는 경우에는 한줄에 하나의 statement만 올 수 있습니다. 따라서 두 가지 일을 하는 statement를 한줄에 쓰려면 세미콜론은 필수입니다. 뭐 그냥 세미콜론을 쓰는게 낫겠죠?

<script language="javascript" type="text/javascript">
<!--
  var1 = 10; var2 = 20;
//-->
</script>

 

 

대소문자를 구분합니다.

자바의 주석처리방식도 지원합니다.

JavaScript 는 C-style 과 C++-style 의 주석처리방식을 지원합니다.

 

 

<script language="javascript" type="text/javascript">
<!--

// This is a comment. It is similar to comments in C++

/*
 * This is a multiline comment in JavaScript
 * It is very similar to comments in C Programming
 */
//-->
</script>

 

 

자, 지금까지 자바스크립트의 기본적인 문법 및 특징에 대해서 알아보았습니다.

 

 

안녕하세요 케이치입니다.

 

오늘은 수많은 소스 정적 분석 툴 중에서 세가지 툴에 대한 비교를 해볼까 합니다.

 

이미 어떤 분이 분석을 해놓은 영문 자료가 있어서 번역을 해보았습니다.

 


   
 Findbugs

 
 PMD
 
 Checkstyle
  버전  3.0.0  5.2.2  6.1.1

  라이센스

 Lesser GNU Public License  BSD-style license  Lesser General Public License
  목적   잠재적 버그 찾기
( 자바 소스파일이 아닌  바이트 코드를 이용 )
   잠재적인 문제들, 버그 가능성이 있는 부분들,
  사용되지 않았거나 최적화되지 않은 코드들 검색
  자바 소스 파일을 읽어서 소스 코드 표준에 위반되는 것들을 검색,
 e.g.  Sun Code Conventions, JavaDoc
 장점 - 실제 결함을 잘 찾아줌
- 찾은 결함이 엉뚱한 결함일 확률이 낮음 ( 정확성이 높음 )
- 바이트 코드를 읽음으로 속도가 빠름
- 종종 실제 결함을 찾아줌
- finds bad practices
 - 정해준 코딩 규약에 위반되는 것들을 검사해줌. 직접 코딩 규약을 만들어 사용가능.
 약점 - 컴파일된 클래스 파일에서 바이트 코드를 읽어서 사용해야하므로 빌드과정이 필수  - 복제된 코드를 찾는 속도가 느림  - 실제 버그를 찾을 수 없음
 규칙 수  408  234  132
규칙 카테고리
 Correctness
 Bad practice
 Dodgy code
 Multithreaded Correctness 
 Performance Malicious 
 Code Vulnerability
 Security Experimental
 Internationalization


 JSP 
 - Basic JSF 
 - Basic JSP
 XSL 
 - XPath in XSL
 Java 

 - Design 
 - Coupling 
 - Jakarta Commons Logging 
 - Basic 
 - Strict Exceptions 
 - Security Code Guidelines 
 - Java Logging 
 - Android -Controversial 
 - Comments 
 - Type Resolution 
 - Empty Code 
 - String and StringBuffer 
 - Code Size 
 - Braces 
 - Unused Code 
 - Unnecessary 
 - J2EE 
 - JavaBeans 
 - Migration 
 - Import Statements 
 - JUnit 
 - Naming 
 - Finalizer 
 - Optimization 
 - Clone Implementation
 Ecmascript
 
 - Basic Ecmascript 
 - Unnecessary 
 - Braces 
 XML
 
 - Basic XML
 Annotations
 Block Checks
 Class Design
 Coding
 Duplicate Code
 Headers
 Imports
 Javadoc Comments
 Metrics
 Miscellaneous
 Modifiers
 Naming Conventions
 Regexp
 Size Violations
 Whitespace

출처 : http://www.sw-engineering-candies.com/blog-1/comparison-of-findbugs-pmd-and-checkstyle

 

2020년 5월 업데이트

실제로 세 가지를 모두 다운로드 받아서 테스트도 해보았고 FindBugs는 실제 서비스에 기능으로 적용도 해보았습니다.

우선 잠재적인 버그 분석을 위해서는 FindBugs가 단연 최고였습니다.

그리고 코딩컨벤션을 정해놓고 확인하기에는 CheckStyle이 좋습니다. 

FindBugs와 CheckStyle은 사용하는 목적 자체가 다른 툴이었습니다.

PMD는 이도저도 아닌 그저그런 툴로 기억합니다.

 

 

--- 이하 최초 발행글 ---

추천 사항

필요에 따라 하나씩만 사용하셔도 되지만 세가지를 모두 사용하시면 좀 더 확실한 정적 툴 분석을 하실 수 있을 것 같습니다.

세 툴을 모두 처음 사용하신다면 제일먼저 FindBugs를 사용하시고 그 다음 PMD 그리고나서 마지막에 CheckStyle을 사용하실 것을 권장드립니다. 이건 다른 분이 하신 말씀이고요....전 CheckStyle만 잠깐 써봤는데요, CheckStyle은 뭐랄까 회사 내부의 코딩 정책을 정의해서 사용하면 좋을만한 그런 툴이더군요. 대신 룰을 너무 과하게 주면 개발자들이 좀 싫어할 수 있을 것 같다는 생각이 드네요.

 

아래 링크는 FindBugs 프로젝트에 참여한 메릴랜드 주립대 교수님의 1시간 분량짜리 세미나입니다.

관심있으신 분들은 보시면 좋을것 같네요. 참고로 언어는 영어입니다.

https://www.youtube.com/watch?v=8eZ8YWVl-2s

 

이상 케이치였습니다.

오늘도 즐프하세요~~ ^-^

 

 

 

 

 

 

INVISIBLE과 GONE의 차이점은 아래와 같습니다.


INVISIBLE:

This view is invisible, but it still takes up space for layout purposes.

GONE:

This view is invisible, and it doesn't take any space for layout purposes.


💻 Programming

[ASM 5.0] 3. BCI를 이용한 클래스 변형하기

이번에는 이전 시간에 만든 writeClass()를 이용해서 생성된 클래스를 변형을 해보도록 하겠습니다.


혹시나 "클래스 생성하기" 챕터를 건너뛰신 분들을 위해서 저~~~~ 아래쪽에 writeClass() 메소드 소스를 올려놓도록 하겠습니다.


자 그럼 시작해볼까요...


변형하는거는 그리 어렵지 않습니다. ClassVisitor를 이용하면 됩니다. 제일 첫번째 시간에 MyClassVisitor를 만들었으니 이걸 이용해보도록 하겠습니다.


큰 그림부터 한번 볼까요?? 순서는 아래와 같습니다.

1. ClassWriter 생성

2. ClassWriter를 이용하여 ClassVisitor 생성 ( ClassWriter를 인자로 넘겨줌 )

3. ClassReader를 이용하여 변형하고자하는 클래스 정보를 읽어들임

4. cr.accept( ClassVisitor, int ) 메소드를 이용해서 클래스 변형


실질적으로 변형을 하는 녀석은 바로 이 ClassVisitor라는 것을 알고 넘어가시면 됩니다.


자, 그럼 우선 클래스를 변형하기위한 메소드를 하나 만들어보죠.

private byte[] transformClass(){
        ClassWriter cw = new ClassWriter(0);
        ClassVisitor cv = new MyClassVisitor(Opcodes.ASM5, cw){};
        ClassReader cr = new ClassReader(writeClass());
        cr.accept(cv, 0);
        return cw.toByteArray();
}


여기서 writeClass()의 소스는 이 포스트 하단에 있습니다.

간단하게 소스설명을 드리자면 우선 cw를 만들고 cv를 생성할 때 인자로 넣어줍니다. 여기서 기존에 만들었던 MyClassVisitor에는 위 소스에서 사용한 생성자가 없으므로 하나를 추가로 생성해주셔야 합니다.

MyClassVisitor클래스에 아래 생성자를 하나 추가해주세요.


public MyClassVisitor(int version, ClassWriter cw) {
        super(version, cw);
}


다시 소스설명으로 넘어와서....

이렇게 cv를 생성을 했으면 이제 변형할 클래스를 읽어옵니다.

그리고 cr의 accept()를 이용해서 방문(?)하면서 변환을 합니다. 이렇게 변환이 된 클래스 정보는 cw에 들어가게 됩니다.


뭔가 간단한것 같으면서도 어지러운것 같죠??


자, 그럼 테스트를 해봐야 하겠죠..

우리가 만들었던 MyClassVisitor의 visit() 메소드를 한번 볼까요?


@Override
    public void visit(int version, int access, String name,
            String signature, String superName, String[] interfaces) {
        name = "BCItest/Modified";
        super.visit(version, access, name, signature, superName, interfaces);
        System.out.println(name + " extends " + superName + " {");
}


자, 위에서 오렌지색으로 표시된 부분이 추가된 부분입니다. 이게 뭘 할건지 짐작이 가시나요?

자 그리고 테스트 클래스에서 지난 시간에 했던 생성된 클래스 테스트해보는 소스를 조금만 수정해보겠습니다.


// 기존 테스트 소스

Class c = new MyClassLoader().defineClass("BCItest.Comparable", writeClass());
System.out.println(c.getName());


// 수정한 테스트 소스

Class c = new MyClassLoader().defineClass("BCItest.Comparable", transformClass());
System.out.println(c.getName());


변경된 부분은 오렌지색으로 표시했습니다.

이렇게 해서 실행을 하면 뭐가 나올까요?


ClassLoader로 읽어오는 과정에서 아래와 같은 오류가 납니다.

java.lang.NoClassDefFoundError: BCItest/Comparable (wrong name: BCItest/Modified)


자....우리가 클래스로더를 이용해서 로드하려고한 클래스명은 Comparable이었는데 transformClass()에서 만들어진 클래스는 Modified이기 때문입니다.

그럼 이번에는 BCItest.Modified를 읽어오도록 해봅시다.


Class c = new MyClassLoader().defineClass("BCItest.Modified", transformClass());
 

위 처럼 defineClass() 메소드에 들어가는 인자를 바꿔주세요.


이제 다시 실행해보면 BCItest.Modified 라고 출력이 되는 것을 확인하실 수 있을겁니다.

참고로 지난번에 했던 MyClassVisitor를 그대로 사용하신다면 클래스 구조가 출력되는 것도 보실 수가 있습니다.


어렵지 않죠?


자 이제 여러분도 BCI의 기본기를 모두 익힌 셈입니다.

클래스 읽기, 쓰기, 수정 까지 했으니까요.


ASM을 이용해서 클래스를 읽어오고, 생성 및 변환하는 부분까지 공부를 해보았는데요


제가 설명하는 능력이 약해서 첫시간부터 지금까지 한 내용을 소스를 첨부했으니 소스를 보면서 천천히 한번 공부해보세요 ^_^


다음시간에는 수정할때 최적화 관련된 부분에 대해서 알아보도록 하겠습니다.


그럼 여러분 안녀~엉~









출처 : ASM 4 가이드 문서






-----------------writeClass()-----------------------

BCItest 패키지를 기준으로 소스가 작성되었습니다.


private byte[] writeClass(){
        ClassWriter cw = new ClassWriter(0);
        cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT + Opcodes.ACC_INTERFACE,
                "BCItest/Comparable", null, "java/lang/Object",
                null);
        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "LESS", "I",
        null, new Integer(-1)).visitEnd();
        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "EQUAL", "I",
        null, new Integer(0)).visitEnd();
        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "GREATER", "I",
        null, new Integer(1)).visitEnd();
        cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "compareTo",
        "(Ljava/lang/Object;)I", null, null).visitEnd();
        cw.visitEnd();

        return cw.toByteArray();
}

💻 Programming

[ASM 5.0] 2. BCI를 이용한 클래스 생성하기

오늘은 클래스를 생성해보는 예제를 가져와봤습니다.


클래스를 생성할때는 ClassWriter 컴포넌트만 필요합니다.


자, 아래와 같은 인터페이스를 ClassWriter를 이용해서 생성해보도록 하겠습니다.


:: 생성하려는 인터페이스

package BCItest;
public interface Comparable extends Mesurable {
    int LESS = -1;
    int EQUAL = 0;
    int GREATER = 1;
    int compareTo(Object o);
}


-- 위 인터페이스를 생성하기위한 소스

private byte[] writeClass(){
        ClassWriter cw = new ClassWriter(0);
        cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT + Opcodes.ACC_INTERFACE,
        "BCItest/Comparable", null, "java/lang/Object",
        new String[] { "BCItest/Mesurable" });
        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "LESS", "I",
        null, new Integer(-1)).visitEnd();
        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "EQUAL", "I",
        null, new Integer(0)).visitEnd();
        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "GREATER", "I",
        null, new Integer(1)).visitEnd();
        cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "compareTo",
        "(Ljava/lang/Object;)I", null, null).visitEnd();
        cw.visitEnd();

        return cw.toByteArray();
}


간 단하게 소스를 훑어볼까요?? 우선 ClassWriter ( 이하 cw ) 인스턴스를 생성하고 visit, visitField, visitMethod 메소드를 호출한 뒤에 마지막으로 visitEnd를 호출했습니다. 각 메소드안에 들어가는 ACC_XXX라는 상수들은 ASM에 미리 정의되어있는 Opcodes 들입니다. Opcodes 인터페이스를 통해서 사용하실 수 있습니다.


필 드 선언부를 보시면 첫번째 필드가 int LESS 라는 필드죠. 우선 인터페이스 내에 선언되어있는 int라서 visitField메소드에서 public, final, static이라는 상수값을 주고 그 다음에 필드명(LESS)과 필드 타입(I)을 주었습니다. 그 다음에 null은 generic관련 필드입니다. 마지막으로는 해당 필드에 할당할 값입니다. 위 예제에서는 new Integer(-1)이죠. 


그리고 cw를 바이트형태로 추출했습니다.

이제 이 바이트 클래스를 이용해서 생성된 인터페이스를 사용해볼까요??


우선 클래스로더가 필요합니다.

아래와 같이 MyClassLoader 클래스를 하나 만들어주세요.

class MyClassLoader extends ClassLoader {
    public Class defineClass(String name, byte[] b) {
        return defineClass(name, b, 0, b.length);
    }   
}


그리고 아래처럼 테스트해보면 됩니다.


Class c = new MyClassLoader().defineClass("BCItest.Comparable", writeClass());
System.out.println(c.getName());


문제가 없다면 BCItest.Comparable 이라고 콘솔창에 출력이 될겁니다.

여 기서 잠깐!!! 제가 실습해본 결과 인터페이스가 Mesurable을 상속하는 형태로 되어있기 때문에 Measurable클래스가 없다면 오류가 납니다. 그래서 1. Measurable을 생성해 주시거나 아니면 2. writeClass()의 cw.visit() 메소드의 마지막 인자인 new String[] { " .... "} 를 null 로 바꿔주시면 실행이 잘 될겁니다.



그럼 다음 시간에는 클래스 변환에 대해서 올리도록 하겠습니다.







출처 : ASM 가이드





💻 Programming

[ASM 5.0] 1. BCI를 이용한 클래스 파일 읽기

BCI ( Byte Code Instrumentation )을 위한 ASM 5.0 프레임 워크에 대해서 공부해볼 예정입니다.

ASM에 대한 사용자메뉴얼 및 개발자가이드는 http://asm.ow2.org/index.html 이곳에서 쉽게 찾을 수 있습니다.

 

오늘은 그 첫 시간. 사용자 메뉴얼을 읽어가면서 조금씩 조금씩 정리해서 블로그에 올릴 예정입니다.

오늘은 클래스 파일 읽어서 정보 얻어오는 부분만 알아보도록 하겠습니다.

 

우선 이클립스에 ASM 5.0 프레임워크를 설치합니다.  

 

http://forge.ow2.org/project/showfiles.php?group_id=23

 

위 링크에 가시면 버전별로 zip 파일을 다운로드 받을 수 있습니다.( 링크가 깨질 것을 염려하여 최신 버전 5.0.3을 첨부하였습니다 )

 

다운로드 받은 zip파일을 압축해제를 합니다.

 

이제 이클립스를 실행시키고 프로젝트에 라이브러리를 추가해주기만하면 됩니다.

 

configure build path하셔서 라이브러리 추가하면 설치 완료!

 

자 이제 프레임워크를 설치했으니 사용해보기로 하죠.

 

BCITest패키지를 만들고 그 밑에 세 개의 클래스 파일을 만듭니다.

 

BCITest.java
HelloWorld.java
MyClassVisitor.java

 

// BCITest.java 소스 ( JUnit Test를 이용했습니다 ) 


package BCItest;

import java.io.IOException;
import org.junit.Test;
import org.objectweb.asm.ClassReader;

public class BCITest {
    @Test
    public void test() throws IOException {
        MyClassVisitor cv = new MyClassVisitor(327680);    // ASM5 = 327680
        ClassReader cr = new ClassReader("BCITest.HelloWorld");       // 대소문자 구분 X ( bcitest.helloworld 라고해도 실행됨 )
        cr.accept(cv, 2);
    }

 

테스트 해보실 때에는 BCITest.HelloWorld 대신에 다른 임의의 클래스를 넣어보시면 됩니다. 예를 들어 java.lang.String이라든가 java.lang.Exception이라든가 하는 클래스들 말이죠.

 

// HelloWorld.java 소스

 

package BCItest;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!!");
    }
}

 

// MyClassVisitor.java 소스

package BCItest;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.TypePath;

public class MyClassVisitor extends ClassVisitor {

    public MyClassVisitor(int arg0) {
        super(arg0);
    }
    @Override
    public void visit(int version, int access, String name,
            String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
        System.out.println(name + " extends " + superName + " {");
    }
    @Override
    public void visitEnd() {
        super.visitEnd();
        System.out.println("}");
    }
    @Override
    public FieldVisitor visitField(int access, String name, String desc,
            String signature, Object value) {
        System.out.println(" " + desc + " " + name);
        return super.visitField(access, name, desc, signature, value);
    }
    @Override
    public MethodVisitor visitMethod(int access, String name,
            String desc, String signature, String[] exceptions) {
        System.out.println(" " + name + desc);
        return super.visitMethod(access, name, desc, signature, exceptions);
    }
}
 

위에서 MyClassVisitor는 ClassVisitor를 상속한 뒤 몇몇 메소드만 오버라이드 했습니다.

 

우선 제가 제공해드린 소스를 기준으로 테스트를 진행하면 아래와 같은 결과가 나옵니다.

 

BCItest/HelloWorld extends java/lang/Object {
 <init>()V
 main([Ljava/lang/String;)V

 

여기서 <init>은 생성자를 말하고 마지막의 V는 void를 의미합니다.  

 

어떤가요? 어렵지 않죠?   

 

HelloWorld 클래스에 메소드를 더 넣어보고 ( 리턴 타입이나 파라미터 개수, 종류를 다르게 해서 ) 테스트해보세요~ 


참고로 아래는 Type Descriptor 와 Method descriptor 입니다.  

 

뭐가 뭘 의미하는지를 나타내주는 거니까 이거는 외우시는게 좋을거에요~







참고로 클래스를 읽어들이는 방법은 BCITest클래스에서 ClassReader생성할 때 이름을 주는 방법 외에 다른 방법도 있습니다.

사 용자 메뉴얼에는 아래와 같이 설명이 되어있습니다. 이름, 값, byte array, input stream을 이용해서 읽어들일 수 있는데 input stream을 이용해서 클래스를 읽어들일 때는 클래스 로더의 getResourceAsStream 메소드를 이용할 수 있다고 합니다. 사용 예제가 바로 밑에 나와있죠?


The class that must be read can be specified by name, as above, or by value, as a byte array or as an InputStream. An input stream to read the content of a class can be obtained with the ClassLoader’s getResourceAsStream method with:

 

cl.getResourceAsStream(classname.replace(’.’, ’/’) + ".class");

 

자, 클래스 파일 읽기는 이쯤에서 끝내겠습니다. 설명이 길면 머리만 아프죠.

 

다음 시간에는 기존의 클래스를 읽는것이 아니라 클래스를 생성해보도록 해보겠습니다~

 

그럼 오늘은 여기서 이만~ 

 

 출처 : ASM 4 사용자 가이드 ( 테스트는 ASM 5 로 했습니다. )






안녕하세요, 조금전에 김프(GIMP) 이미지툴을 소개해 드렸었는데요


잠깐 써봤더니 이게 벡터이미지를 그리는 툴은 아닌것 같아서

벡터이미지 툴을 다시 검색해서 찾아낸 따끈한 벡터이미지 툴을 소개합니다.


그 이름하야 Inkscape 입니다.


이 역시 윈도우, 맥, 리눅스에서 사용가능한 크로스 플랫폼 툴입니다.


아래는 잉크스케이프의 홈페이지입니다.

다국어 처리가 되어있어서 들어가면 바로 한국어로 뜹니다.

(이미지를 클릭하면 홈페이지로 이동합니다.)







상단 메뉴에도 있고 우측에도 다운로드 버튼이 잘 보이네요.

저는 우측에 새 부리가 가리키는 다운로드 버튼을 클릭했습니다.



OS별로 다운로드할 수 있도록 되어있습니다.

제일 좌측의 펭귄이 리눅스용이고 가운데가 윈도우용 제일 우측이 맥용입니다.


전 지금 윈도우 컴퓨터 앞에 앉아있으니 가운데 윈도우 로고 그림을 클릭하겠습니다.




윈도우는 또 32비트와 64비트가 있으니 한번 더 선택을 해야합니다. 제 컴퓨터는 64비트이므로 64비트용 아래쪽 이미지를 클릭해서 설치파일을 다운로드 받아서 실행시켰습니다.



셋업화면은 다국어처리가 안되있네요.



라이센스 동의에 체크를 하고 다음~~




뭐 기본설정으로 설치할거냐 알아서 선택할거야 전부 다 할거냐 물어보는 화면은 많이들 보셨죠? 까이꺼 대충 그냥 Typical로 설치해봅시다.



Install 클릭! 클릭!




설치가 완료되었습니다!!!! 우와!!!!!

이제 나도 게임케릭터를 벡터이미지로 그릴수 있다!!!

포토샵 일러스트 필요없다!!! 우하하!!!


이상 친절한 케이치였습니다.


^-^ ㅎㅎ


좋은하루 되세요 여러분~~



안녕하세요 케이치입니다~


오늘은 무료 이미지 편집 툴을 소개해 드리려 합니다.


제가 요새 안드로이드 게임 개발을 독학으로 하고있습니다.


근데 게임이란게 모든 파트가 다 중요하지만 그 중에서도 사람들의 시선을 끄는 멋있는 그래픽이 아무래도 가장 중요하지 않나 싶습니다.


전 개발자이지 디자이너는 아니지만 사람들의 첫인상이 중요한것처럼 게임의 첫인상도 중요한데 그 첫인상은 바로 이 그래픽이라고 생각합니다.


여기서 그래픽이라는건 뭐 해상도가 좋은 3D 그래픽 이런걸 말하는게 아니고요 그냥 2D라도 좀 더 귀엽고 이쁘고 깔끔한 그런 그림을 말하는 거에요 ^-^


서두가 좀 길었네요.



제가 이번에 소개해드리는 툴은 GNU 라이센스를 갖고있는 GIMP (GNU Image Manupulation Program) 라는 툴입니다.


Mac, Windows, Linux에서 사용이 가능한 멀티플랫폼 툴입니다.


아래는 GIMP의 홈페이지입니다. ( 아래 이미지를 클릭하시면 김프 홈페이지로 이동합니다. )




역시 Download 버튼은 눈에 띄게 해놓았네요. 다운로드 버튼을 클릭합니다~~ 그럼 아래와 같은 화면이 나옵니다.

전 윈도우에서 클릭하니까 아래처럼 for Windows 버전을 다운로드하도록 나오는데 아마 다른 OS 쓰시는 분들은 해당 OS용 GIMP 다운로드 링크가 나올겁니다.







자, 그럼 Download 버튼을 클릭합니다. 두개가 있는데 주황색으로 된 버튼을 선택하시면 되요~


다운받아서 설치파일을 실행시키면 아래처럼 Setup 언어를 선택하라고 나오는데 한국어는 없네요.


저는 영어를 잘하니까 그냥 영어 선택합니다 ㅋㅋㅋㅋ






그랬더니 아래처럼 시원한 바다속에서 숨못쉬고있는데 웃고있는 검은여우같은 녀석이 나오네요.





그냥 Install 버튼 클릭! 클릭!


아래처럼 설치가 시작이 됩니다...





아래는 설치가 완료된 화면이구요





이제 실행시켜봐야겠죠??




셋업때에는 영어로만 나왔는데 셋업하니까 프로그램 내부적으로 다국어 처리를 해놨는지 한글로 나옵니다.






뭔가 포토샵과 비슷한 분위기가 있는것 같네요.


이상 케이치였습니다~~


읽어주셔서 감사합니다.~ ^-^


후덥지근한 여름 건강 조심하시구요~


모두 즐프하세요~~~


-------------- updated -------------------

김프 2.4 한글판 메뉴얼 링크 ( GIMP Korean Manual )





안녕하세요~케이치입니다~

 방금 전에 포스팅 했었는데 너무 길어지는 것 같아서 끊고 또 포스팅하네요 ㅎㅎ


지난 시간에는 배경화면 넣고 땅도 만들어보고 케릭터도 넣어서 움직여봤습니다.


그런데 문제가 하나있었죠? 보통 화살표를 누르고있으면 계속 연속적으로 움직여줘야 하는데 그렇게 되지 않았던 거죠.


자, 그 해결방법은 생각보다 간단합니다.


우선 수정된 Player 소스를 보여드릴게요 ~

public class Player extends Actor {

private Sprite characterSprite;

boolean leftMove;
boolean rightMove;

float x;

Player(){
characterSprite = new Sprite(new Texture("player.png"));
characterSprite.setBounds(Gdx.graphics.getWidth()/2-100, 100,
 
Gdx.graphics.getWidth()/10, Gdx.graphics.getHeight()/5);
}
public Sprite getCharacterSprite(){
return characterSprite;
}
public void updateMotion(){
if ( leftMove ){
x = characterSprite.getX() - 5;
characterSprite.setX(x);
}
if ( rightMove ){
x = characterSprite.getX() + 5;
characterSprite.setX(x);
}
}

public void setLeftMove(boolean t){
if ( rightMove && t ) rightMove = false;
leftMove = t;
}
public void setRightMove(boolean t){
if ( leftMove && t ) leftMove = false;
rightMove = t;
}
}

setLeftMove와 setRightMove 그리고 updateMotion이라는 메소드가 새로 생겼네요.


그럼 이번엔 CharacterProcess의 소스가 어떻게 바뀌었는지 볼까요??

@Override
public boolean keyDown(int keycode) {
System.out.println("keycode : " + keycode);
switch(keycode){
case 21:
player.setLeftMove(true);
break;
case 22:
player.setRightMove(true);
break;
}
return true;
}

@Override
public boolean keyUp(int keycode) {

switch(keycode){
case 21:
player.setLeftMove(false);
break;
case 22:
player.setRightMove(false);
break;
}
return true;
}

네, 위 처럼 keyUp 메소드를 새롭게 구현해줬고요 keyDown메소드는 뭔가 되게 간단해졌네요 그쵸? ^-^


이렇게 수정하면 키 이벤트 처리는 끝난겁니다. 에? 이게 뭐냐구요?

한번 소스를 간략하게 설명드릴게요 ^-^ 저는 친절한 케이치니까요 ㅎㅎㅎ

자, 일단 간단하게 바뀐 CharacterProcess에서의 처리부터 한번 보시죠.

왼쪽 화살표 키가 눌리면

1. player.setLeftMove(true)를 호출합니다.

2. setLeftMove(true)가 호출되면 아래 로직을 따라갑니다.

 - 만약 오른쪽으로 이동중이었다면 rightMove를 false로 변경합니다.

 - 무조건 leftMove를 true로 변경합니다.

3. 끝


왼쪽 화살표 키가 올라가면 

1. player.setLeftMove(false)를 호출합니다.

2. setLeftMove(false)가 호출되면 아래 로직을 따라갑니다.

 - if문에서 false와 && 조건이 맞물리면서 if문은 실행되지 않습니다.

 - 무조건 leftMove를 false로 변경합니다.


오른쪽 화살표 키가 눌리거나 올라갔을 때도 동일한 로직을 따라갑니다.


자, 여기서 하는 일은 키가 눌렸을 때 케릭터의 이동을 결정짓는 boolean값을 변경하기만 하는 일을 합니다. 좌표를 변경한 것도 아니고 아직 화면에 뿌려지는 것이 아닙니다.


자 그럼 메인 클래스에서는 뭐가 수정이 됐는지 한번 보실까요?

    @Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.disableBlending();
batch.draw(background, 0, 0, 800, 480);
batch.enableBlending();
// let's draw ground image
batch.draw(groundTextureRegion, backgroundPos, 0, 800, 100);
if ( backgroundPos + 800 > 0 && backgroundPos + 800 < 800){
batch.draw(groundTextureRegion, backgroundPos + 800, 0, 800, 100);
}
// let's draw player
inputProcessor.getPlayer().getCharacterSprite().draw(batch);
batch.end();
updateScene();
inputProcessor.getPlayer().updateMotion();

}


자, 메인 클래스에서 변경된 부분은 render()메소드의 마지막 줄에 inputProcessor.getPlayer().updateMotion() 메소드가 호출됐다는 것입니다. 저게 무슨 메소드였는지 위에서 보셨나요?

그냥 지나친 분들을 위해서 아래 다시 보여드릴게요.


    public void updateMotion(){
if ( leftMove ){
x = characterSprite.getX() - 5;
characterSprite.setX(x);
}
if ( rightMove ){
x = characterSprite.getX() + 5;
characterSprite.setX(x);
}
}

이 메소드는 위에서 Player클래스에 새로이 추가되었던 메소드입니다.

여기서 하는 일은 Player객체가 가지고있는 leftMove와 rightMove 불리언 값에따라 케릭터의 좌표를 변경해주는 일을 합니다.

단순히 좌표만 변경합니다.


그리고 메인 클래스에서 이 케릭터를 뿌리고있죠.


이제 이렇게 수정된 소스를 실행해보세요.


방향키를 누르고있는 동안 케릭터가 계속 움직입니다.


아, 그리고 전에는 왼쪽 오른쪽 방향에 대해서 케릭터가 스크린에서 벗어날 수 없도록 했었는데 이번에 수정하면서 그부분이 빠졌네요.


화면에서 사라지지는 못하도록 여러분들이 한번 조건을 넣어보세요~~~  ^-^ 히힛~ 숙제입니다~~~


그리고 점프기능이나 뭐 이런것들을 넣으면 재밌겠죠? ㅋㅋ


그럼 오늘은 이만 줄이겠습니다.


계속 장맛비가 내리는데 곰팡이 조심하시고 즐프하세요~~ ㅋㅋ


이상 친절한 케이치였습니다.






그저께 그래픽 출력하기 1편을 포스팅 했었는데 소스가 없었죠? 어제 올리려 했는데 일이 좀 바빠서 오늘 포스팅합니다.

 

자!!!!

 

오늘은 제가 만든 소스와 이미지 파일을 모두 공유할 예정이니 잘 따라와만 주신다면 여러분들도 멋진 게임을 만드실 수 있습니다 ㅋㅋ

( 저도 처음인데 이런 말을 하고있네요 ㅋㅋㅋ)

 

저와 같은 안드로이드 스튜디오를 사용하고 libGDX가 설치되어있으며 이곳의 설정(assets)을 똑같이 하셨다는 가정하에 진행합니다. 그리고 테스트는 안드로이드 폰이 아닌 데스크탑에서 진행합니다. ( 아직 폰에서는 테스트를 못해봤습니다. )

 

 

질문 있으시면 댓글 남겨주세요.

 

그럼 시작합니다.

 

오늘 보시게될 소스는 아래와 같이 실행이 됩니다.

 

 

 

땅은 왼쪽으로 계속 움직이는 것 처럼 보이고 케릭터는 왼쪽, 오른쪽 화살표로 이동이 가능합니다.

 

 

1. 추가된 파일 및 클래스 ( 소스 실행에 필요한 추가된 이미지 파일은 첨부하였습니다. )

- carl-carlson.jpg는 없어도 되는 파일인데 들어가있네요 ㅈㅅ;;;;

 

 

 

2. 첨부된 파일을 다운받아 해당 위치 ( android/assets )에 넣어주세요.

3. core에 있는 소스는 아래와 같습니다.

 

우선 Player 입니다.

 

 

 

 

 

 

 

자, 플레이어는 게임속 주인공 케릭터입니다. Sprite를 이용해서 뿌려줄거구요 setBounds메소드를 이용해서 케릭터의 사이즈를 지정해줬습니다. 그리고 외부에서 characterSprite를 불러쓸 수 있도록 getter를 하나 선언해줬죠.

 

다음은 CharacterProcessor입니다.

 

 

CharacterProcessor가 InputProcessor를 구현하면 그 안에 각종 메소드들을 오버라이드해야하는데 저는 keyDown메소드만 구현을 했고 나머지 메소드들은 기본으로 놔두었습니다.

 

일단 기본적으로 플레이어를 하나 생성해서 들고있고 그 플레이어에대한 getter인 getPlayer()를 만들어줬습니다.

 

이제 키보드 입력을 받아서 케릭터를 움직이기위해 keyDown메소드를 구현합니다.

 

여기서 keycode 21은 왼쪽, 22를 오른쪽 화살표를 말합니다.

왼쪽화살표가 눌리면 좌측으로 이동하는데 조건이 있습니다. 화면의 가장 좌측까지 도달하면 더이상 움직이지 않도록 if 조건을 주었습니다. 오른쪽으로 이동하는것도 마찬가지로 동일한 방법으로 처리했습니다.

 

 

자, 이제 메인클래스인 MyGdxGame 클래스를 보실까요?

public class MyGdxGame extends ApplicationAdapter {
    SpriteBatch batch;
    Texture background;
    Texture terrain;
    TextureRegion groundTextureRegion;
    float backgroundPos = 0;
    CharacterProcessor inputProcessor;

    @Override
    public void create () {
        batch = new SpriteBatch();
        background = new Texture("sky2.jpg");
        terrain = new Texture("grey_stone_1.png");
        terrain.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);
        groundTextureRegion = new TextureRegion(terrain);
        inputProcessor = new CharacterProcessor();
        Gdx.input.setInputProcessor(inputProcessor);
    }
    @Override
    public void render () {
        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();
        batch.disableBlending();
        batch.draw(background, 0, 0, 800, 480);
        batch.enableBlending();
        
        // let's draw ground image
        batch.draw(groundTextureRegion, backgroundPos, 0, 800, 100);
        if ( backgroundPos + 800 > 0 && backgroundPos + 800 < 800){
            batch.draw(groundTextureRegion, backgroundPos + 800, 0, 800, 100);
        }

        // let's draw player
        inputProcessor.getPlayer().getCharacterSprite().draw(batch);

        batch.end();

        updateScene();
    }
    private void updateScene(){
        float deltaTime = Gdx.graphics.getDeltaTime();
        backgroundPos -= 200 * deltaTime;
        if ( backgroundPos <= -800 ){
            backgroundPos = 0;
        }
    }
}

 

 

우선 create()에서는 대부분의 객체를 초기화해주었습니다.

 

render()에서는 뿌려주는 것을 담당하는데 게임이 실행되는동안 끊임없이 호출되는 메소드인것 같습니다.

 

enableBlending으로 배경(sky2.jpg)위에 땅(grey_stone_1.png)과 케릭터(player.png)를 그릴 수 있도록 해주었습니다.

 

땅을 그릴때는 batch.draw()에서 TextureRegion을 이용했고, 케릭터는 Sprite.draw를 이용했습니다.

 

그리고 땅을 그릴때 땅이 좌측으로 계속 이동하면서 마치 케릭터가 우측으로 이동하는것 같은 효과를 줄 수 있도록 해보았습니다.

 

updateScene()에서 그 효과를 줄 수 있도록 backgroundPos ( 땅 그림이 뿌려질 위치 )를 변경해주고있습니다.

 

자, 그런데 이렇게 하면 화살표를 계속 누르고 있어도 한번 밖에 움직이지 않습니다.

 

이부분에 대해서는 다음 포스팅에서 해결방법을 알려드리도록 하겠습니다.

 

그럼 오늘도 즐프하시길 ~ ^-^

 

지금까지 libGDX를 독학하고있는 케이치였습니다~

 

P.S : 도움이 되셨으면 댓글 하나 남겨주세요 ^-^

 

 

 

 

 

 

[[ 원본 이미지 파일첨부 ]]

 

 

 

 

 

안녕하세요, 오늘도 어김없이 꿀팁을 들고온 케이치입니다 ^-^ ㅎㅎ

 

오늘은 안드로이드 스튜디오에서 기본적으로 보여주지 않고있는 메소드 description에 대한 것입니다.

 

이클립스는 기본적으로 메소드 위에 마우스 커서를 올려놓으면 메소드에대한 설명이 나오는데요

 

안드로이드 스튜디오는 기본적으로 그렇지가 않더군요. ㅜㅜ

 

구글링하면 나오기는 하는데 2014년도 버전과 최근 없데이트된 버전이 또 조금 다르더군요.

 

자, 우선 메소드 설명을 보는 방법 몇 가지를 소개해드리겠습니다.

 

 

 

1. description을 보고자하는 메소드명에 커서가 위치하도록 마우스로 클릭하고 Ctrl + Q ( Windows )를 누른다.

 

아래는 Texture에다가 커서가 깜박이도록 한 뒤 Ctrl + Q 를 눌렀을 때 나오는 팝업입니다.

 

 

 

 

2. 이클립스처럼 마우스 커서를 올려만 놔도 자동으로 메소드 디스크립션을 띄우려면

File >> Setting >> Editor >> General >> Other >> Show quick doc on mouse move 에 체크를 해줍니다.

 

 

 

3. 세번 째는 수동으로 파일을 수정하는 방법입니다.

 

IntelliJ의 bin디렉토리에 보시면 idea.properties라는 파일이 있는데 여기에 auto.show.quick.doc=true 를 추가해주시면 됩니다. 

 

이 세번째 방법은 직접 검증 해보진 않았고 구글링에서 나온 얘기를 그냥 덧붙인것입니다. 첫번째, 두번째 방법처럼 쉬운 방법이 있는데 궂이 이 방법을 쓸 이유는 없겠죠? ㅋ

 

 

자~ 그럼 오늘도 즐프~~

 

 

 

 

libGdx 프로젝트 생성 직후 기본적으로 안드로이드 버전은 테스팅이 원활히 진행이 된다.

 

하지만 데스크탑 버전으로 테스팅하려고 하면 아래와 같은 에러가 발생한다.

 

    Exception in thread "LWJGL Application" com.badlogic.gdx.utils.GdxRuntimeException: Couldn't load file: badlogic.jpg
        at com.badlogic.gdx.graphics.Pixmap.<init>(Pixmap.java:140)
        at com.badlogic.gdx.graphics.TextureData$Factory.loadFromFile(TextureData.java:98)
        at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:100)
        at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:92)
        at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:88)
        at com.mygdx.game.MyGdxGame.create(MyGdxGame.java:18)
        at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:143)
        at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:120)
    Caused by: com.badlogic.gdx.utils.GdxRuntimeException: File not found: badlogic.jpg (Internal)
        at com.badlogic.gdx.files.FileHandle.read(FileHandle.java:136)
        at com.badlogic.gdx.files.FileHandle.readBytes(FileHandle.java:222)
        at com.badlogic.gdx.graphics.Pixmap.<init>(Pixmap.java:137)
        ... 7 more

    Process finished with exit code 0

 

 

해결 방법은 아래와 같다.

 

1. 이클립스 사용자의 경우

Run => Run Configurations.. => DesktopLauncher 의 Arguments 탭 => Working Directory => Others then browse to yourproject-android/assets/ and click Apply => Run

 

 

 

 

 

 

 

2. 안드로이드 스튜디오의 경우

 

  1. Run -> Edit Configurations

  2. "Working Directory:" 를 가면 기본적으로 안드로이드 스튜디오 프로젝트 최상위 디렉토리로 설정되어있는데 => "android/assets" 디렉토리까지 들어가도록 설정

     

 

 

 

 

이제 다시 실행해보시면 잘 될겁니다.

 

 

즐프~

 

 

 

 

- 이건 제가 LibGDX Game Development Essentials 라는 책을 보면서 정리한 내용으로 제가 정확히 이해하지 못한 부분에 대해서는 여러분들이 알고있는 것과 차이가 있을 수 있음을 말씀드리며, 혹여나 제가 잘못 이해한 부분이 있으면 댓글로 저에게 지식을 좀 나누어 주시면 감사하겠습니다. ^-^



오늘은 Displaying graphics에 대해서 포스팅을 하려합니다.

일 단 Texture가 뭔지에 대해서 이해를 해야할 것 같네요. Texture란 GPU로 이미지가 전달되는 단위(?)라고 생각하시면 됩니다. 그런데 이게 expensive process라서 좀 더 효율적으로 그리기 위한 도구가 필요했는데 그래서 나온것이 SpriteBatch입니다.


SpriteBatch 클래스는위치 정보를 이용해서 좀더 효율적으로 그림을 그릴 수 있도록 도와주는 클래스입니다. 동일한 Texture를 여러군데에 뿌려줘야할 때 유용하게 쓰입니다. 하지만 만약 Texture가 바뀌게되면 비효율적인데요 이럴 때는 texture packing과정을 통해서 여러 이미지를 하나의 큰 이미지로 합쳐서 사용하게 됩니다.


TextureRegion이라는 클래스를 사용할 수도 있습니다. TextureRegion은 Texture의 조각이라고 생각하시면 됩니다. Texture의 일부를 떼어낸 것이죠. 예를들어, 일반적인 벽지는 무늬가 반복이 되죠? 이 반복되는 무늬를 TextureRegion이라고 보시면 됩니다.


또 다른 방법은 Sprite 클래스를 이용하는 방법입니다. Sprite클래스는 Texture와 위치 정보, 사이즈 정보를 함께 합쳐놓은 클래스입니다. 따라서 화면에 그림을 그릴 때 draw코드내에 위치정보나 사이즈 정보를 입력하지 않아도 됩니다. 대부분의 경우 Sprite클래스를 사용하면 편리하다고 합니다.


자, 그럼 이 세가지를 어떤 경우에 써야 할까요?


일단 간단한 게임을 하나 만든다고 생각해봅시다.


우 선 배경(1)이 있고 그 위에 그려지는 여러 장애물들(2)이 있고, 마지막으로 배경이 움직이는 것처럼 보일 수 있도록 게임진행 내내 스크롤링이 되는 구름배경이나 땅이 움직이는 것처럼 보이도록 해주는 부분(3)이 있다고 가정해보죠.


1번같은 경우에는 그냥 고정해놓으면 됩니다. 따라서 Texture를 이용하면 됩니다.

2번의 경우에는 계속 움직여야되는 아이템들이라 Sprite를 이용합니다.

3번의 경우에는 TextureRegion을 이용합니다. 보이지 않는 스크롤링 효과를 만들기 위해서 여러번 그림을 그려줘야 하기 때문이죠.


자, 여기까지 정리를 해보자면 그래픽 출력하기에는 세가지 방식이 있습니다.


1. SpriteBatch

2. TextureRegion

3. Sprite


아직 저도 많이 사용해보질 않아서 어떤 경우에 이렇게 써야한다라고 딱 잘라서 말할 수는 없지만, 지금 당장은 위에 잠깐 설명드린대로 사용하시면 될것 같습니다.



( 조만간 간략한 소스까지 올리도록 하겠습니다. )



오류 메시지 : 새로운 apk의 버전 코드(1)가 이미 존재합니다.


해결방법 : 

AndroidManifest.xml 파일에서 


android:versionCode=""

android:versionName=""


를 찾을 수 있다면 해당 값을 변경해주시면 됩니다.


참고로 버전 코드는 몇 번째 업데이트인지를 표시해주시면되고 버전 네임에는 실제 사용자들에게 보여지는 버전입니다.


구글링 하면 대부분 위와같은 방법으로 해결하신 것 같은데 아마도 이클립스에서 안드로이드 개발 하시던 분들이 올린 글인것 같습니다.


저같은 경우는 안드로이드 스튜디오로 개발을 하고있는데 특별히 세팅을 바꾼게 없는데 manifest파일에 위와같은 설정이 없길래 그냥 수동으로 추가해보려했더니 warning이 떴는데 그래들 빌드에서 값을 오버라이드 하고 있다고 나오더군요.


만약 manifest파일에 저런 설정이 없다면 안드로이드 스튜디오 좌측 패키지 익스플로러 창에서 트리 표시 방법을 Android로 선택을 해주시면 build.gradle ( Module:app )을 열어보시면 versionCode와 versionName 설정하는 곳이 보이실 겁니다.


아래 사진을 참고하세요.






그럼 즐프하세요~ ^-^



💻 Programming/Computer General

맥(Mac) 스크린샷 단축키

맨날 까먹어서 아예 포스팅해버립니다. 또 까먹을까봐 ㅜㅜ


Mac에서 스크린샷 찍는 단축키입니다.


command + shift + 3 : 전체화면을 스크린샷 

command + shift + 4 + sapce + window클릭 : 선택한 어플리케이션 영역을 스크린샷
command + shift + 4 + 마우스로영역지정 : 마우스로지정한 영역만 스크린샷



안녕하세요~


libGdx 코너가 새롭게 마련되었습니다. 제가 이번에 libGdx를 이용한 게임을 개발할 예정이라 게임을 개발하면서 생긴 libGdx관련 오류나 팁을 공유하기 위해서 게시판을 생성하였습니다. ^-^


libGDX가 뭐냐? 국내에서는 Cocos 시리즈가 게임 개발에 많이 사용되고 있습니다만 외국에서는 libGDX 사용자들도 많습니다. 자바에 익숙하신 분들이라면 쉽게 사용할 수 있는 자바기반이구요, Cocos2d-x 처럼 CrossPlatform 입니다. 하나의 소스만 개발해서 데스크탑에서도 테스트해보실 수 있고 안드로이드, iOS, HTML로도 테스트가 가능하도록 구성되어있습니다. 무료 개발 툴 치고는 상당히 좋은 툴이라고 생각됩니다.


자~ 오늘은 libGdx 설치하는 것 부터 해보도록 하죠~


그 전에 제 환경은 아래와 같습니다.





그리고 이클립스는 버리고 안드로이드 스튜디오를 사용하고 있습니다.


자, 우선 libGdx 사이트로 가서 다운로드를 받아야 겠죠?


http://libgdx.badlogicgames.com/download.html
libgdx
libgdx.badlogicgames.com
본문으로 이동


위 링크를 따라가시면 아래처럼 다운로드 링크가 큼지막하게 보이실겁니다.






다운로드링크를 클릭하시면 gdx-setup.jar 파일을 다운로드 하게 됩니다.


이제 다운로드한 jar 파일을 실행시키세요.


혹시 시스템 보안 설정에 확인된 게시자가 만든 앱만 실행 가능하도록 해놓으셨다면 실행이 안될 겁니다.


그럴경우에는 터미널 창을 열어서 직접 


java -jar gdx-setup.jar 


명령어를 입력해주시거나 아니면 시스템 환경설정 > 보안 및 개인정보에 가시면 강제실행할 수 있는 버튼이 있을 겁니다. 그걸 눌러주시면 되요.


자, 셋업 프로그램이 실행이 되면 아래와 같은 화면이 나올겁니다.



Name 에는 애플리케이션 명을 넣어주시면 되고 패키지는 뭐 안드로이드 패키지 넣듯이 넣어주시면 됩니다.

게임 클래스는 자바 클래스 파일 명을 말하는거고(앱 이름과 동일하게 주시면 됩니다. 그냥 메인 클래스 파일 이름 넣어주시는거니까요 )

Destination은 프로젝트가 설치될 디렉토리 경로인데 저는 안드로이드 스튜디오를 이용할 것이기 때문에 안드로이드 스튜디오 안에 디렉토리를 만들고 그 디렉토리로 설정을 해주었습니다.

Android Sdk 경로는 안드로이드 스튜디오를 이미 사용하신 분들이면 안드로이드 스튜디오 처음 실했하자마자 설정메뉴로 들어가시면 찾으실 수 있고요 아니면 터미널 창에서 find 명령어로 찾으실 수도 있습니다. 예를들면 find / -name android 뭐 이렇게 주면 됩니다.


LibGDX Version은 그대로 놔두시면 됩니다.


그리고 그 밑에 Sub Projects는 기본적으로 모두 다 선택되어있습니다. 근데 저는  html을 해제시켰습니다. 필요없으니까요.

데스크탑은 혹여나 폰없이 데탑에서 테스트 하고 싶을 수도 있을 것 같아서 그냥 넣어봤습니다.


Extensions 에 있는 것은 외부 라이브러리들입니다. 기본적으로 Box2d가 선택되어져있구요 저는 Tools와 Ai를 추가로 선택했습니다.

각 외부라이브러리 이름에 마우스 커서를 올려놓으면 이게 어떤 것들인지 간략하게 설명을 해주니까 여러분들도 필요할것 같아 싶은게 있으면 체크해주시면 됩니다.


자, 그리고 그 밑에  "Show Third Party Extensions"라고 버튼이 하나 있는데 그걸 누르시면 아래와 같은 팝업창이 하나 뜹니다.




기본적으로 모든 체크박스가 해제되어있는데 저는 그냥 다 선택해봤습니다. 혹시 필요할까해서 말이죠 ㅋ 그리고 Save.


다시 원래 화면으로 돌아와서 이제 Generate 버튼을 클릭하시면 각종 라이브러리를 다운받고 빌드를 시작합니다.

이때 빌드툴 버전에 대해서 팝업창이 뜰 수가 있는데 그냥 Yes, Yes 하시면 됩니다. ^-^


저같은 경우는 약 8분정도 걸렸네요. 사실 이것도 여러번 한겁니다. 처음에는 로보vm 라이브러리 다운받다가 시간 엄청 오래걸리고 무슨 에러가 나는데 뭐 제가 할 수 있는 거라고는 위에 체크박스 설정하는 것 뿐인데 구글링해도 답은 안나오고....그냥 여러번 시도하다가 간신히 빌드가 성공적으로 되는 걸 확인할 수 있었습니다.


자, 이렇게 빌드가 성공적으로 됐다면 이제 빌드된 프로젝트를 안드로이드 스튜디오에서 열어서 실행시켜보면 됩니다.


아래그림처럼 안드로이드 스튜디오를 실행시키시고 Import project를 선택을 합니다.


그리고 libGdx설치할 때 주었던 Destination 경로 디렉토리를 선택해주시면 아래처럼 빌드를 또 시작합니다.


저같은 경우는 아래 과정도 꽤나 오래걸렸습니다. 이거 뭐 바로바로 되는게 없더군요. 여러분들은 한번에 성공하시길 바랍니다.


 



자, 빌드를 마치면 프로젝트 화면이 뜹니다. 그리고 바로 실행을 시키시면 유명한 배드로직 초기화면이 뜰겁니다.


자, 이상으로 libGdx 설치하는 법에 대해서 알아보았습니다.


모두 좋은 하루 되세요~

안녕하세요~


오늘은 무료 사운드 에디터를 하나 소개할 까 합니다.


뭐 저도 필요해서 다운받아서 잠깐 써본거 말고는 아는게 없어서 장황하게 설명드릴건 없고요


직접 다운 받아서 사용해보시면 될것 같아요~


윈도우(Windows), 맥(Mac), 리눅스(Linux)를 모두 지원하는 무료, 오픈 소스, 크로스 플랫폼 소프트웨어입니다.


아래 공식 홈페이지로 가시면 Download 링크가 엄청 커다랗게 있어요.


공식 홈페이지 : http://web.audacityteam.org/


7월 22일 현재 15년 7월 15일자 최신 버전이 올라와 있네요.







💻 Programming/WAS

[JBoss 7] module.xml 에서 모듈 설정하기

Jboss AS 7 에서 module.xml 설정을 위한 간략한 설명을 적어놓은 좋은 자료를 찾아서 포스팅 해봅니다.

영문이긴하지만 어려운 말은 없으니 한번 읽어보시길 바랍니다 ^-^ 



Full module.xml example with comments 


    <?xml version="1.0" encoding="UTF-8"?> 
     
    <module xmlns="urn:jboss:module:1.1" name="org.jboss.msc"> 
     
        <!-- Main class to use when launched as a standalone jar. --> 
        <main-class name="org.jboss.msc.Version"/> 
     
        <!-- Properties readable through Modules API. Not to be confused with Java system properties. --> 
        <properties> 
            <!-- jboss.api=private means that the module is not part of the JBoss AS 7 public API - basically saying, "Don't use it's packages in your apps." --> 
            <property name="jboss.api" value="private"/> 
        </properties> 
     
        <resources> 
            <!-- Basically, list of jars to load classes and resources from. --> 
            <resource-root path="jboss-msc-1.0.1.GA.jar"/> 
            ... 
        </resources> 
     
        <dependencies> 
     
            <!--  Export paths and packages from the class loader which loaded JBoss Modules (usually the system's application CL). --> 
            <system export="true"> 
                <!-- List of exported paths. Mandatory. --> 
                <paths> 
                   <path name="org/jboss/modules"/> 
                   <path name="org/jboss/modules/log"/> 
                </paths> 
                <!-- Optional limitation of what's exported. --> 
                <exports> 
                     <include path="META-INF/"/> 
                </exports> 
            </system> 
     
            <!-- Dependencies on other modules. Classloader of this module will have their classes visible. --> 
            <module name="javax.api"/> 
            <module name="org.jboss.logging"/> 
     
            <!-- services="import/export/none" controls whether services defined in META-INF/services are also visible to/from this module. 
                   I.e. services="export" will make the services of this module visible to the dependency. Import will do the other way around. 
                   Defaults to "none". --> 
            <!-- export="true" controls whether own exports of this dependency are visible. --> 
            <module name="org.jboss.ws.native.jbossws-native-core" services="export" export="true"> 
                <!-- You can limit what packages in dependency modules are allowed  
                       to be seen from this module's point of view (import), or vice versa (export). 
                       By default, all are imported/exported. When you specify <imports> or <exports>, only those listed are. --> 
                <imports> 
                   <include path="META-INF"/> 
                   <include path="dtd"/> 
                   <include path="schema"/> 
                   <exclude-set> 
                       <path name="org.jboss.example.tests"/> 
                   </exclude-set> 
                </imports> 
                <exports> 
                    <include path="META-INF"/> 
                    <include path="dtd"/> 
                    <include path="schema"/> 
                </exports> 
            </module> 
     
            <!-- Optional deps --> 
            <module name="javax.inject.api" optional="true"/> 
        </dependencies> 
    </module> 


- See more at: https://developer.jboss.org/people/ozizka/blog/2012/11/12/about-modulexml-in-jboss-as-7#sthash.oZ0bLEzI.dpuf



출처 : https://developer.jboss.org/people/ozizka/blog/2012/11/12/about-modulexml-in-jboss-as-7